<pre class="metadata">
Title: Encrypted Media: Encryption Scheme Query
Repository: wicg/encrypted-media-encryption-scheme
Issue Tracker Template: https://github.com/wicg/encrypted-media-encryption-scheme/issues/{0}
Status: CG-DRAFT
ED: https://wicg.github.io/encrypted-media-encryption-scheme/
Shortname: encrypted-media-encryption-scheme
Level: 1
Group: wicg
Editor: Joey Parrish, w3cid 105371, Google Inc. https://google.com/

Abstract: This is an extension to the W3C Encrypted Media Extensions
Abstract: specification, to be integrated into EME vNext. The API will allow
Abstract: authors to query support for specific encryption schemes in the CDM.

!Participate: <a href="https://github.com/wicg/encrypted-media-encryption-scheme">Git Repository.</a>
!Participate: <a href="https://github.com/wicg/encrypted-media-encryption-scheme/issues/new">File an issue.</a>
!Version History: <a href="https://github.com/wicg/encrypted-media-encryption-scheme/commits">https://github.com/wicg/encrypted-media-encryption-scheme/commits</a>
</pre>

<pre class="anchors">
spec: webidl; urlPrefix: https://heycam.github.io/webidl/
    type: dfn
        text: present; url: #dfn-present

spec: encrypted-media; urlPrefix: https://www.w3.org/TR/encrypted-media/
    type: interface
        text: MediaKeySystemMediaCapability; url: #dom-mediakeysystemmediacapability
        text: Get Supported Capabilities...; url: #get-supported-capabilities-for-audio-video-type
        text: requestMediaKeySystemAccess(); url: #navigator-extension:-requestmediakeysystemaccess()
        text: MediaKeySystemAccess; url: #dom-mediakeysystemaccess
        text: getConfiguration(); url: #dom-mediakeysystemaccess-getconfiguration
        text: Clear Key; url: #clear-key

spec: html51; urlPrefix: https://www.w3.org/TR/html51/
    type: dfn
        urlPrefix: semantics-embedded-content.html
            text: media data; url: #media-data
</pre>

<!--
<pre class="biblio">
</pre>
-->

<section>
  <h2 id="mediakeysystemmediacapability-extension">
    MediaKeySystemMediaCapability dictionary extension
  </h2>

  <pre class="idl">
    partial dictionary MediaKeySystemMediaCapability {
      DOMString? encryptionScheme = null;
    };
  </pre>

  <p>
    The {{encryptionScheme}} field indicates an encryption scheme required by
    the application in combination with the other fields of the
    {{MediaKeySystemMediaCapability}} dictionary.  A value which is null or
    <a>not present</a> indicates to the user agent that no specific encryption
    scheme is required by the application, and therefore any encryption scheme
    is acceptable.

    NOTE: Applications that are aware of this field should always specify a
    value.  See [[#application-notes]] for details.

    NOTE: If {{encryptionScheme}} is <a>not present</a>, the
    {{encryptionScheme}} field of the {{MediaKeySystemMediaCapability}} object
    returned from {{MediaKeySystemAccess}}.{{getConfiguration()}} must be
    <a>present</a> and set to the default value of null.  This enables detection
    of this feature in polyfills for user agents which do not support this
    field.  See also [[#polyfills]].

    NOTE: The empty string is distinct from null or <a>not present</a>, and so
    would be treated as an unrecognized encryption scheme.

    Well-known values for {{encryptionScheme}} are:
        - <dfn>cenc</dfn>: The "cenc" mode, defined in ISO 23001-7:2016, section
                           4.2a.  AES-CTR mode full sample and video NAL
                           subsample encryption.
        - <dfn>cbcs</dfn>: The "cbcs" mode, defined in ISO 23001-7:2016, section
                           4.2d.  AES-CBC mode partial video NAL pattern
                           encryption.  For video, the spec allows various
                           encryption patterns.
        - <dfn>cbcs-1-9</dfn>: The same as "cbcs" mode, but with a specific
                               encrypt:skip pattern of 1:9 for video, as
                               recommended in ISO 23001-7:2016, section 10.4.2.

    NOTE: The document WebM Encryption defines WebM encryption to be equivalent
          to and compatible with the "cenc" encryption mode defined in ISO
          23001-7:2016.

    ISSUE(#9): A registry should be created for encryption schemes, and the
    existing format registry should be updated with respect to encryption
    schemes.
  </p>
</section>

<section>
  <h2 id="algorithm-extension">
    Algorithm Extensions
  </h2>

  <p>
    In the {{Get Supported Capabilities...}} algorithm, the following changes
    should be made:

    1. In the loop that begins with "For each <var>requested media
        capability</var> in <var ignore> requested media capabilities</var>",
        the user agent MUST run the following steps at the beginning of the
        loop:

        1. Let |encryption scheme| be |requested media capability|'s
            {{encryptionScheme}} member.

        1. If |encryption scheme| is non-null and is not recognized or not
            supported by the user agent, continue to the next iteration.

    1. In the step that says "If the user agent and |implementation| definitely
        support playback of encrypted <a>media data</a> for the combination of
        |container|, |media types|, |robustness| and |local accumulated
        configuration| in combination with |restrictions|", the user agent MUST
        replace the condition with the following condition:

        1. If the user agent and |implementation| definitely support playback of
            encrypted <a>media data</a> for the combination of |container|,
            |media types|, |robustness|, |encryption scheme|, and |local
            accumulated configuration| in combination with |restrictions|...
  </p>
</section>

<section>
  <h2 id="clearkey-requirements">
    Clear Key Requirements
  </h2>

  <p>
    {{Clear Key}} implementations MUST support the <a>cenc</a> scheme at a
    minimum, to ensure interoperability for users of this common key system.
  </p>
</section>

<section class="non-normative">
  <h2 id="application-notes">
    Application Notes
  </h2>

  <p>
    Applications that are aware of the {{encryptionScheme}} field should always
    specify the encryption scheme(s) they require, since different encryption
    schemes are generally incompatible with one another.  It is unrealistic for
    an application to be accepting of "any" encryption scheme, but the default
    of null and the interpretation of null as "any" provide backward
    compatibility for unaware applications and a path to a polyfill for older
    user agents.  See also [[#polyfills]].
  </p>

  <p>
    Applications may specify multiple encryption schemes in separate
    [[encrypted-media#dom-mediakeysystemconfiguration|configurations]], or in
    multiple [[encrypted-media#dom-mediakeysystemmediacapability|capabilities]]
    of the same configuration.
  </p>

  <p>
    The user agent only selects one configuration.  So if different encryption
    schemes are specified in separate configurations, the application will be
    given back a configuration containing only one encryption scheme.
  </p>

  <p>
    If different encryption schemes appear in the same configuration, the user
    agent's accumulated configuration will contain the supported subset of the
    capabilities specified by the application.  The configuration returned from
    {{getConfiguration()}} may therefore contain more than one encryption
    scheme.
  </p>
</section>

<section class="non-normative">
  <h2 id="polyfills">
    Polyfills and Backward Compatibility
  </h2>

  <p>
    Omission of {{encryptionScheme}} is supported only to maintain backward
    compatibility for applications that are unaware of this field.  Applications
    should always specify the encryption scheme(s) they require.  See also
    [[#application-notes]].
  </p>

  <p>
    Applications which do not specify {{encryptionScheme}} will get the same
    behavior they did before this feature existed: encryption scheme will not be
    considered during {{requestMediaKeySystemAccess()}}, and they will have to
    make assumptions about which encryption scheme(s) the user agent supports.
  </p>

  <p>
    User agents which implement this specification will always have an
    {{encryptionScheme}} field in the {{MediaKeySystemMediaCapability}} object
    returned from {{MediaKeySystemAccess}}.{{getConfiguration()}}, even if the
    field is <a>not present</a> in the {{MediaKeySystemMediaCapability}} object
    given by the application.  This enables a
    <a href="https://remysharp.com/2010/10/08/what-is-a-polyfill">polyfill</a>
    to be written which detects the lack of {{encryptionScheme}} to determine
    whether or not a browser supports it.
  </p>

  <p>
    If the user agent does not support the {{encryptionScheme}} field, a
    polyfill can use assumptions about the encryption scheme(s) supported by
    various user agents to emulate this specification and reject
    {{MediaKeySystemMediaCapability}} objects which specify (assumed)
    unsupported schemes.  Note that these are the same assumptions already made
    by existing applications.  A polyfill would allow an application to offload
    those assumptions.  The application could then always use the
    {{encryptionScheme}} field to specify their needs using a standard API.
  </p>

  ISSUE(#13): Publish and link to a polyfill for this feature.

  <p>
    Any user agent which deprecates support for an existing encryption scheme
    could introduce backward compatibility issues for older applications which
    do not use this new feature.  Appropriate communication with developers will
    be necessary to ensure that applications are updated in a timely manner
    ahead of any such deprecation.  The need for good communication around
    deprecations is not unique to this proposal.
  </p>
</section>

<section class="non-normative">
  <h2 id="security-privacy-considerations">
    Security and Privacy Considerations
  </h2>

  <section>
    <p>
      This specification does not introduce any security-sensitive information
      or APIs.
    </p>

    <section>
      <h3 id="fingerprinting">
        Fingerprinting
      </h3>

      <p>
        This extension offers an additional field an application can use to
        determine the device's decryption capabilities.  This does not increase
        the fingerprint surface by much, since decryption capabilities are
        generally the same for any given user agent and operating system.  This
        extension simply offers applications a way to avoid hard-coding this
        knowledge.
      </p>
    </section>

    <section>
      <h3 id="user-consent">
        User Consent
      </h3>

      <p>
        Fingerprinting concerns are mitigated by the fact that this new field is
        part of the {{requestMediaKeySystemAccess()}} API, which
        may require user consent.  User agents that would require user consent
        in order to access the CDM will therefore require user consent to make
        use of this new field.
      </p>
    </section>
  </section>
</section>

<section>
  <h2 id="examples">Examples</h2>

  <div class="example" highlight="javascript">
    <pre>
function tryTwoEncryptionSchemesInSeparateConfigurations(keySystem) {
  // Query two configurations with different encryption schemes.
  // Only one will be chosen by the user agent.

  return navigator.requestMediaKeySystemAccess(keySystem, [
    { // A configuration which uses the "cenc" encryption scheme
      videoCapabilities: [{
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cenc',
      }],
      audioCapabilities: [{
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cenc',
      }],
      initDataTypes: ['keyids'],
    },

    { // A configuration which uses the "cbcs-1-9" encryption scheme
      videoCapabilities: [{
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cbcs-1-9',
      }],
      audioCapabilities: [{
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cbcs-1-9',
      }],
      initDataTypes: ['keyids'],
    },
  ]);
}
    </pre>
  </div>

  <div class="example" highlight="javascript">
    <pre>
function tryTwoEncryptionSchemesInOneConfiguration(keySystem) {
  // Query one configuration with two different encryption schemes.
  // The user agent will eliminate any capabilities object it cannot support,
  // so the accumulated configuration may contain one encryption scheme or both.

  return navigator.requestMediaKeySystemAccess(keySystem, [{
    videoCapabilities: [
      { // A capability object which uses the "cenc" encryption scheme
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cenc',
      },
      { // A capability object which uses the "cbcs-1-9" encryption
        // scheme
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cbcs-1-9',
      },
    ],
    audioCapabilities: [
      { // A capability object which uses the "cenc" encryption scheme
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cenc',
      },
      { // A capability object which uses the "cbcs-1-9" encryption
        // scheme
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cbcs-1-9',
      },
    ],
    initDataTypes: ['keyids'],
  }]);
}
    </pre>
  </div>
</section>
