HTML/Media Task Force/EME Use Cases

From W3C Wiki

Use Cases

This section lists user-observable use cases.

  • One application and media file can be used on multiple user agents and clients with different key systems: Supported
  • Notification of encrypted media data: Supported (encrypted event)
  • Online streaming of a single title: Supported
  • Offline viewing of a single title: Supported ("persistent-license" sessionType, load())
  • Live streaming of a single event: Supported
  • Continuous streaming of multiple titles: Supported (application-driven)
  • Multiple keys:
    • Various streams for a single title use different keys: Supported (both single and multiple sessions)
    • Keys for multiple titles are loaded to accelerate playback: Supported (both single and multiple sessions)
  • Abnormal situations are handled or can be reported to the user:
    • Waiting for a usable key: Supported (waitingforkey Event - this is really an error and not intended to be recoverable)
    • License lost due to device sleep, etc.: Supported (closed promise attribute)
    • Expired license: Supported (TBD mechanism to report, expiration attribute)
    • Output protection issues: Supported (TBD mechanism)
    • Downscaling of content: (need mechanism to report to application)

Key Delivery Mechanisms

This section lists the various ways keys might be delivered to a CDM via EME. Not all of the mechanisms listed are required or supported by all Key Systems.

  • Intermediate keys (provided via license request & update()): Not Currently Supported
  • Title keys embedded in the media resource (other than the initData portion): Not Currently Supported
  • Title keys embedded in initData (provided via generateRequest(initData)): Not Currently Supported
    • Question: Would a license request still be generated or would the initData contain all necessary information?
    • This is currently under discussion in Issue 53 and Issue 41.
  • Title keys provided from license server: Supported (via license request & update())
  • Title keys provided from application: Supported (via license request & update())

Roots of Trust

  • Key System global keys: Supported (via Key System-/implementation-specific mechanism)
  • Client-specific keys: Supported (via Key System-/implementation-specific mechanism)
  • Device-specific keys: Supported (via Key System-/implementation-specific mechanism)
  • Application-specific keys: Supported (via one-time license request & update())

Application Models

The following sections describe application models or designs that address one or more of the use cases above. (This is not an exhaustive list.)

Simple Streaming of a Specific Title

Status: Supported

Required: YES

This is the primary use case that EME is modeled around. It is simple and thus can be supported consistently by multiple key systems without additional complexities.

  • The media resource is online or in application storage.
  • The (multiple) audio and video streams are encrypted with content decryption keys that do not change for a given stream. The streams may share a key or use different keys.
  • The license is in the application or will be requested by the application from an online server known to the application.
  • The application and/or its server authenticates the user.
  • The application and/or its server uses the authenticated identity and license request to decide whether to grant the license and which policies it contains.
  • The application selects a key system-media combination it supports using navigator.requestMediaKeySystemAccess(). It uses this information to determine the license server and media streams to provide. Ideally, the rest of the application is independent of this information.
  • The license request is generated based on Initialization Data that the application obtains from one of the following:
    • The media stream(s) via encrypted event(s)
    • The application, including from the server or a manifest
  • The license contains the content decryption key(s) for the streams.
  • No keys, licenses, or information about the session or its ID are persisted or stored.
  • During playback, only licenses/keys in session(s) created by the MediaKeys object are used to decrypt the media data.
  • Simultaneous playbacks may be restricted using expiring licenses, expiring constantly-renewed licenses, and/or key release messages.

License Exchange Flow

  • The application creates a session by calling createSession("temporary").
  • The application initiates a license request/challenge by calling generateRequest().
  • The CDM generates a license request using the provided Initialization Data.
  • The application receives the license request via a message event.
  • The application likely provides the request to the server and receives a response.
  • The license server generates a license based on the key IDs and/or other information in the license request.
  • The application provides the license via update().

Related Bugs

Keys Available in initData

Status: Supported

Required: NO

Some DRMs are able to derive a content key based on encrypted keys or seed values found in the PSSH. The mechanism for deriving a content key based on a DRM-specific PSSH is also DRM-specific (barring issue #53 being resolved). For these DRMs, a license request may be unnecessary if the keys necessary to decrypt the content can be extracted and made available when the session is created. Rather than force the CDM to generate unnecessary network traffic, this use case allows the CDM to avoid the license request step by indicating to the browser that no message needs to be sent, while updating the key status map to indicate that keys are available.

License Exchange Flow

  • createSession(session-type)
  • generateRequest() requests a license (not necessarily persistent).
  • The CDM determines whether a key is available or can be generated directly from the intiData passed to generateRequest.
  • If the answer is NO -- the CDM behaves as in the Simple Streaming Model.
  • If the answer is YES -- the CDM extracts or otherwise generates a key and calls the key status update passing the browser the key ID. No request is generated, so there is no encrypted message sent by the browser to the application.
  • The application can monitor for the keystatuseschange event to check for key availability.

Note that no caching should occur unless the session has been requested as persistent-license.

Persisted License / Offline

Status: Supported

Required: NO

Same as the Simple Streaming model except as described in the following sections.

Initial License Exchange Flow

  • createSession("persistent-license")
  • generateRequest() requests a persistable license.
  • The application handles the resulting message and obtains a license in the same way as the Simple Streaming model.
  • The application calls update() to provide the license.
  • The CDM stores the license (and other session information) with the sessionId.
  • The application stores the sessionId (for later retrieval) and media resource (the streams) in application storage.
  • Optional: Repeat the above steps for other sessions.

First Playback

Playback can begin at any time (encrypted frames require that the license has been provided()). There are no special operations required to use the persistent license.

The application can obtain the streams from anywhere, though a reasonable approach is to store them in application storage then retrieve them for playback in the same way as subsequent playbacks.

Subsequent Playback

  • The application determines the session ID(s) of the session(s) to load for a given title based on information stored in application storage.
  • createSession("persistent-license")
  • load(sessionId) to load the persisted license.
    • Note: The session/license may contain multiple keys and/or there may be multiple sessions.
    • Note: If the license was removed but the record was not acknowledged, the CDM generates a message for the license destruction record and provides it in a message event of type "license-release". No keys are loaded.
  • Optional: Repeat the above steps for other sessions.
  • The application loads the media resource from application storage (in the offline case) and plays.
  • Only licenses/keys in session(s) created or loaded by the MediaKeys object are used to decrypt the media data.

License Removal

  • When the user/application no longer wishes to persist the license, the application calls remove() to remove it.
  • The CDM destroys the license and stores a record of the license's destruction.
    • Note: Until the record is sent to the server, acknowledged, and removed (below), a message will be sent (as in the step below) each time this session is loaded.
  • The CDM generates a message for the license destruction record and provides it in a message event of type "license-release".
  • The application sends the message to the server.
  • The server generates an acknowledgement, which the application provides to the CDM via update().
  • Upon receiving the acknowledgement, the CDM erases the license destruction record and all other records of the session.
  • The application erases its record of the session, including sessionId from application storage when the promise returned by update() is resolved.
  • (The application likely also erases the media resource (the streams) from application storage.)

Related Bugs

Bug 24771 - Provide guidance on object and CDM lifetime (including when events are guaranteed to be fired)
Bug 25268 - Reduce the burden on applications to deduplicate initData from many needkey events

Enforcement of Limited Concurrent Streams via Key Renewal

Status: Supported

Required: Recommended

An application may want to restrict the number of concurrent playbacks (i.e. per user/account, possibly per title). This can be accomplished using short license durations with renewal. If a new playback starts causing the authorized limit to be exceeded, subsequent renewals of other license(s) can be denied. This provides the desired behavior for the user without the client complexity and potential false positives of client-based solutions.

Same as the simple streaming model except:

  • The initial license has a short duration and is renewable.
  • The CDM periodically requests a renewal license via a message event. The resulting renewal licenses also have short duration.

Questions

  • Does the application need to control the timing of the renewal requests ?

No. This is a policy, which the license server specifies in the license like other policies. The timing and other aspects are enforced by the CDM.

  • Can a response to a renewal request still be used with update() after the existing license has expired ?

This is probably implementation-dependent (i.e. CDMs are allowed to close expired sessions). I don't think this is an issue in practice since renewal requests should occur well before expiration. Am I missing something?

  • How long is the renewal request value ? i.e. how long should the application continue retrying it ? If the renewal request is not valid indefinitely, how should the application trigger a new one ?

The expiration time and renewal periods are (currently) implementation-dependent. They could be fixed in the CDM or (more likely) specified in the license. The CDM issues renewal requests based on this information, and the application passes them along. The application doesn't need to worry about timing, etc. If there is a network failure, the application might retry (just as it might for regular license requests). If a response is not received, the CDM will send another renewal request after some period.

(Some of the above questions may apply to regular license requests too)

Related Bugs

Bug 26600 - Text is confused between persistent session vs persistent licenses

Bug 24771 - Provide guidance on object and CDM lifetime (including when events are guaranteed to be fired)

Bug 25268 - Reduce the burden on applications to deduplicate initData from many needkey events

Detection of Concurrent Stream Usage via Key Release

Status: Supported

Required: NO

Many services, in particular subscription services, need to limit the number of concurrent streams available on any given account. This is typically achieved by maintaining a record of the number of streams in progress at the application server. This record is kept up-to-date through interaction between the client side Javascript application and the application server. This mechanism is subject to attack if the client side Javascript is modified in order to interfere with this interaction, leaving the application server with an incorrect view of the number of streams in progress.

Requirement: The basic requirement addressed here is to detect, offline, accounts where application server sessions-in-progress counts were inaccurate.

The secure key release mechanism enables a service to detect this, after-the-fact, through reconciliation of application server streaming records with CDM generated records. The application server has accurate information about when a license was granted, but is missing reliable information about when a license was first used and in particular when it was destroyed. This mechanism provides that information from the CDM. It is more difficult to interfere with this information reporting than with the client Javascript application: specifically the information from the CDM can be blocked / supressed, but cannot eaily be modified. The service provider can thus detect fraud in two ways:

  • CDM-provided information regarding key use is mismatched with application server records, for example if the application server records indicate a session lasted 10 seconds but the CDM records indicate 1 hour. This may indicate that application server interaction was deliberately suppressed or modified.
  • CDM-provided information is reported much less frequently for an account. This may indicate that the CDM-reported information itself is being suppressed.

The CDM-provided information is provided in two ways:

  • the client application can trigger the release of the keys explicitly with the remove() method and this triggers the generation of a secure release message at that time
  • if the keys are released implicitly (e.g. due to window or browser close or crash), then persisted information about the session may be retrieved in a further browsing session and the secure release message obtained at that time

The CDM-provided information needs to consist of:

  • an indication that keys were released and the IDs of the keys
  • a correlation with the original license granted
  • the first and last times the license was used for decryption, preferably accurate to within <tbd> seconds

The mechanism can be described in terms of a key release record which is created and persisted when keys are destroyed. However, practical implementations cannot always persist information at the time of key destruction (especially if that is caused by a crash) and so instead, what may be persisted is information about keys presently in use and it is a future discrepancy between this persisted information and the keys actually available in the session which triggers the generation of a key release record.

In practice, there will be a small fraction of sessions for which this key release record is not available: the larger this fraction the less robust the mechanism is at detecting users who are exceeding concurrent stream usage restrictions and so the requirements on fraction of sessions with key release are service-provider-specific.

Example usage

Key release records may be used by the service provider to detect when an account has exceeded concurrent stream limits as follows. The following algorithm may be executed by the service provider's servers: First, we must suppose that such records are available for all devices associated with the account. The input data, for a specific time period, is the following:

  • The number of sessions (i.e. licenses granted) for the account
  • A set of key release records, each containing a start and end time
  • The accuracy of the timestamps provided by the CDM (this is a property of the keysystem / platform which we assume is known to the server).

The following Javascript code snippet calculates the maximum number of concurrent streams for the account in the time period in question, giving the benefit of the doubt to the customer with respect to the accuracy of the timestamps (note: we use Javascript for convenience, although this algorithm would be executed on the server side):

// Inputs
// * records - an Array of records in the format described in License Release Record
// * accuracy - accuracy of the timestamps, in milliseconds

var max_cocurrent_streams = records
	.reduce( function( out, in ) {
			out.push( { t: in.tfirst, v: 1 } );
			out.push( { t: Math.max( in.tfirst, in.tlast - accuracy ), v: -1 } );
			return out;
		}, [])
	.sort( function( a, b ) { return ( a.t === b.t ) ? b.v - a.v : a.t - b.t; } )
	.reduce( function( out, in ) {
			out.count += in.v;
			out.max = Math.max( out.max, out.count );
			return out;
		}, { count: 0, max: 0 } )
	.max;

Clearly, if the algorithm above is based only on key release messages and indicates that concurrent stream limits have been exceeded then this is a very strong indication (to CDM robustness) that those limits have indeed been exceeded. As a result, it's likely that a practical attack would seek to suppress the delivery of the key release messages. It will be necessary for the service provider to distinguish between the case where key release messages are missing for "normal" reasons and deliberate suppression. "Normal" reasons will likely be somewhat device-specific but could include crashes, sudden loss of power, clearing of persisted data (by the user) or simply that the user does not visit the site again on that device.

If either the maximum number of concurrent streams exceeds the account limit, or if the number of key release records is less than the number of sessions by more than some service-provided-specific threshold, then the account may be flagged as suspect.

If an account is flagged as suspect there are a number of possible mitigations:

  • If a specific circumvention tool is suspected, users may be presented with warnings that use of that tool is not allowed under the terms of service
  • Service provider client code may be updated to (at least temporarily) disable the circumvention
  • The account may be subjected to more aggressive rules for the determination of concurrent streams in real-time (including, for example, license renewal techniques)
  • The account may be suspended or closed

The choice of response is one for the service provider an will be very dependent on the nature of the attack / circumvention and other aspects of their service design.

Application Flow

Playback
  • Application calls createSession("persistent-release-message") to create a session that will persist the release message (but not the license).
  • The application stores the sessionId in application storage.
  • Per the policy in the license, the CDM may persist information about the session but does not persist the keys.
  • Application loads the media resource and plays back.
  • When playback is complete, the application calls remove() to start the Key Release Handshake.
  • Per the policy in the license, the CDM destroys the keys and generates a receipt. The receipt may be persisted.
  • Continue to the next section.
Key Release Handshake
  • CDM queues a message event containing the receipt.
  • Application sends the contents of the message event to the license server. The application may also send additional information about the original session.
  • License server acknowledges the receipt and informs the application.
  • Application calls update() to provide the acknowledgement
  • CDM removes the receipt and other information about the session.
  • Upon success, the application removes the sessionId in application storage.
Failed Handshake

It is not required to attempt the handshake except by the explicit procedure described above (for example if the web application is closed or crashes). If the explicit procedure is not completed before page close, then on a subsequent session:

  • The application may then use load() to reload the session.
  • Assuming the load() succeeds, the application should then call remove() to start the Key Release Handshake.
  • This causes the CDM to queue a message event containing the same receipt. The same Key Release Handshake flow is run.

Questions (and Answers)

  • How does the session usage relate to persistent licenses? Both are persistent sessions. The license itself is likely not persisted.
  • Should remove impact persistent licenses? Or is that orthogonal? remove() removes the persisted session information. In this case, the license/key(s) were not persisted, but other tracking information has been persisted.
  • Is the only use case for session loading the key release scenario? No, see Persisted License / Offline.
  • Does this mean that the promise returned from remove() should not be finalized until the update() has been received?

Related Bugs

Issue 45 - Remove "persistent-release-message" MediaKeySessionType

License/Key Rotation

Status: Supported

Required: YES

Same as the simple streaming model except:

  • The application provides sets of key(s) as needed, using one of the following mechanisms:
    • Updating the current session/license with additional keys.
    • Creating additional session(s).
      • Initialization Data from encrypted events or otherwise known to the application, such as via a manifest, is used to create new sessions.

Related Bugs

Bug 25268 - Reduce the burden on applications to deduplicate initData from many needkey events

Multiple License Sessions

Status: Supported

Required: YES

When displaying a large set of video titles, an application may want to create sessions for many of them near-simultaneously in order to accelerate playback once a title is chosen.

There are a couple of mechanisms in place that can be used to support this.

  • Create a session(s) for each individual title.
  • Accumulate the set of needed keys for all relevant titles and create a single session for all of them by passing the appropriate Initialization Data representing all such titles to generateRequest().
    • This can be done using the [IDs Initialization Data] format (recommended).
    • Or constructing a single container-specific Initialization Data value.

The license exchange flow is the same as the simple streaming model. The only difference is that the except the license request and license contain keys for multiple different titles.

Related Bugs

Bug 25268 - Reduce the burden on applications to deduplicate initData from many needkey events
Issue 53 - Allow for long-lived key encryption keys (aka "master" keys) to increase performance

Bit rate adjustment based on content downscaling

TODO: Break out downscaling from the already supported usable key scenario.

Status: Not Yet

Required: NO

When viewing an HD title, local conditions and the content policy applied by the publisher may result in the content being downscaled prior to playback, for example because output protection requirements could not be met. CDM implementors would like to be able to notify the application when this is occurring so that the application can download lower quality (and presumably less bandwidth intensive) content instead. This could be done using the keystatuseschange event notification.

Application Flow

  • The application initiates a license request/challenge by calling createSession() then generateRequest().
  • The application receives a keystatuseschange event with the data indicating downscaling is happening (this indicator is the missing part).
  • The application loads an alternative stream (if available) and starts over again

Related Bugs

Bug 25092 - Need a way to inform script that resolution restrictions are applied

Bug 24874 - Positive isTypeSupported() may be misleading (MSE vs. .src=)

Federated Content Playback

Status: TBD

Required: NO

In this use case, a single player is designed to playback content from multiple content distributors (e.g. Ultraviolet). The key servers that must ultimately issue keys for this content may not be known to the player in advance. There are various potential models for supporting this.

1. The URL for key requests is provided by the CDM with the key message (current model) 2. The URL for key requests is provided by the CDM embedded in the key message, application parses out URL 3. The URL for key requests is provided by the CDM embedded in the key message, application sends to static URL(s) and front-end server parses out the URL

The workflow would be the same as the simple streaming model in case (1) and would only vary slightly in case (2) and case (3). Discussion is ongoing in the bugs as to which approach is best. We have largely decided not to support this for phase 1, but we don't want to code ourselves into a corner either.

Related Bugs

Bug 26683 - Replace MediaKeyMessageEvent's "destinationURL" attribute with a "type" attribute
Bug 25920 - Remove extraction of default URL from createSession() algorithm
Bug 26401 - Key message destinationURL usage is not reflected in examples