chromium/ash/components/arc/mojom/oemcrypto.mojom

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Next MinVersion: 5

// The original version of this file lives in the Chromium repository at:
// src/components/arc/mojom/oemcrypto.mojom

// This file defines the mojo interface between Android, Chrome and the
// Chrome OS daemon for the Widevine L1 OEMCrypto implementation used in ARC++.
// This file matches what's in Widevine's OEMCryptoCENC.h file closely and all
// methods are documented there.

// Version 1 of this interface supported OEMCrypto v11 and is now deprecated.
// Version 2 supports OEMCrypto v14.
// Version 3 maintains backwards compatibility with version 2 and supports
// OEMCrypto v15.
// Version 4 maintains backwards compatibility and supports OEMCrypto v16.
// Version 5 adds the v16 CopyBuffer variant.

module arc.mojom;

[Stable, Extensible]
enum OemCryptoResult {
  SUCCESS = 0,
  ERROR_INIT_FAILED = 1,
  ERROR_TERMINATE_FAILED = 2,
  ERROR_OPEN_FAILURE = 3,
  ERROR_CLOSE_FAILURE = 4,
  ERROR_ENTER_SECURE_PLAYBACK_FAILED = 5,
  ERROR_EXIT_SECURE_PLAYBACK_FAILED = 6,
  ERROR_SHORT_BUFFER = 7,
  ERROR_NO_DEVICE_KEY = 8,
  ERROR_NO_ASSET_KEY = 9,
  ERROR_KEYBOX_INVALID = 10,
  ERROR_NO_KEYDATA = 11,
  ERROR_NO_CW = 12,
  ERROR_DECRYPT_FAILED = 13,
  ERROR_WRITE_KEYBOX = 14,
  ERROR_WRAP_KEYBOX = 15,
  ERROR_BAD_MAGIC = 16,
  ERROR_BAD_CRC = 17,
  ERROR_NO_DEVICEID = 18,
  ERROR_RNG_FAILED = 19,
  ERROR_RNG_NOT_SUPPORTED = 20,
  ERROR_SETUP = 21,
  ERROR_OPEN_SESSION_FAILED = 22,
  ERROR_CLOSE_SESSION_FAILED = 23,
  ERROR_INVALID_SESSIONS = 24,
  ERROR_NOT_IMPLEMENTED = 25,
  ERROR_NO_CONTENT_KEY = 26,
  ERROR_CONTROL_INVALID = 27,
  ERROR_UNKNOWN_FAILURE = 28,
  ERROR_INVALID_CONTEXT = 29,
  ERROR_SIGNATURE_FAILURE = 30,
  ERROR_TOO_MANY_SESSIONS = 31,
  ERROR_INVALID_NONCE = 32,
  ERROR_TOO_MANY_KEYS = 33,
  ERROR_DEVICE_NOT_RSA_PROVISIONED = 34,
  ERROR_INVALID_RSA_KEY = 35,
  ERROR_KEY_EXPIRED = 36,
  ERROR_INSUFFICIENT_RESOURCES = 37,
  ERROR_INSUFFICIENT_HDCP = 38,
  ERROR_BUFFER_TOO_LARGE = 39,
  [MinVersion=2] WARNING_GENERATION_SKEW = 40,  // Warning, not an error.
  [MinVersion=2] ERROR_GENERATION_SKEW = 41,
  [MinVersion=2] LOCAL_DISPLAY_ONLY = 42,  // Info, not an error.
  [MinVersion=2] ERROR_ANALOG_OUTPUT = 43,
  [MinVersion=2] ERROR_WRONG_PST = 44,
  [MinVersion=2] ERROR_WRONG_KEYS = 45,
  [MinVersion=2] ERROR_MISSING_MASTER = 46,
  [MinVersion=2] ERROR_LICENSE_INACTIVE = 47,
  [MinVersion=2] ERROR_ENTRY_NEEDS_UPDATE = 48,
  [MinVersion=2] ERROR_ENTRY_IN_USE = 49,
  [MinVersion=2] ERROR_USAGE_TABLE_UNRECOVERABLE = 50,  // Reserved. Do not use.
  [MinVersion=2] KEY_NOT_LOADED = 51,
  [MinVersion=2] KEY_NOT_ENTITLED = 52,
  [MinVersion=3] ERROR_BAD_HASH = 53,
  [MinVersion=3] ERROR_OUTPUT_TOO_LARGE = 54,
  [MinVersion=3] ERROR_SESSION_LOST_STATE = 55,
  [MinVersion=3] ERROR_SYSTEM_INVALIDATED = 56,
  [MinVersion=4] ERROR_LICENSE_RELOAD = 57,
  [MinVersion=4] ERROR_MULTIPLE_USAGE_ENTRIES = 58,
  [MinVersion=4] WARNING_MIXED_OUTPUT_PROTECTION = 59,
  [MinVersion=4] ODK_ERROR_CORE_MESSAGE = 1000,
  [MinVersion=4] ODK_SET_TIMER = 1001,
  [MinVersion=4] ODK_DISABLE_TIMER = 1002,
  [MinVersion=4] ODK_TIMER_EXPIRED = 1003,
  [MinVersion=4] ODK_UNSUPPORTED_API = 1004,
  [MinVersion=4] ODK_STALE_RENEWAL = 1005,
};

[Stable]
struct OemCryptoSecureBuffer {
  // buffer_handle should be passed to the ProtectedBufferManager service in
  // the GPU in order to retrieve the shared memory handle that corresponds
  // to the actual secure buffer. It should then be mapped and data written at
  // offset up until offset + max_length.
  handle buffer_handle;
  uint32 max_length;
  uint32 offset;
};

[Stable, Extensible]
enum OemCryptoCipherMode {
  CIPHER_MODE_CTR = 0,
  CIPHER_MODE_CBC = 1,
};

[Stable, Extensible]
enum OemCryptoLicenseType {
  CONTENT_LICENSE = 0,
  ENTITLEMENT_LICENSE = 1,
};

[Stable]
struct OemCryptoSubstring {
  uint32 offset;
  uint32 length;
};

[Stable]
struct OemCryptoKeyObjectV14 {
  uint32 key_id_offset;
  uint32 key_id_length;
  uint32 key_data_iv_offset;
  uint32 key_data_offset;
  uint32 key_data_length;
  uint32 key_control_iv_offset;
  uint32 key_control_offset;
  OemCryptoCipherMode cipher_mode;
};

[Stable]
struct OemCryptoKeyObject {
  OemCryptoSubstring key_id;
  OemCryptoSubstring key_data_iv;
  OemCryptoSubstring key_data;
  OemCryptoSubstring key_control_iv;
  OemCryptoSubstring key_control;
};

[Stable]
struct OemCryptoEntitledContentKeyObjectV14 {
  array<uint8> entitlement_key_id;
  array<uint8> content_key_id;
  array<uint8, 16> content_key_data_iv;
  array<uint8> content_key_data;
};

[Stable]
struct OemCryptoEntitledContentKeyObject {
  OemCryptoSubstring entitlement_key_id;
  OemCryptoSubstring content_key_id;
  OemCryptoSubstring content_key_data_iv;
  OemCryptoSubstring content_key_data;
};

[Stable]
struct OemCryptoKeyRefreshObjectV14 {
  uint32 key_id_offset;
  uint32 key_id_length;
  bool has_key_control_iv;
  uint32 key_control_iv_offset;
  uint32 key_control_offset;
};

[Stable]
struct OemCryptoKeyRefreshObject {
  OemCryptoSubstring key_id;
  OemCryptoSubstring key_control_iv;
  OemCryptoSubstring key_control;
};

[Stable, Extensible]
enum OemCryptoAlgorithm {
  AES_CBC_128_NO_PADDING = 0,
  HMAC_SHA265 = 1,
};

[Stable]
struct OemCryptoCencEncryptPatternDesc {
  uint32 encrypt;
  uint32 skip;
  uint32 offset;
};

[Stable, Extensible]
enum OemCryptoUsageEntryStatus {
  UNUSED = 0,
  ACTIVE = 1,
  INACTIVE = 2,
  INACTIVE_USED = 3,
  INACTIVE_UNUSED = 4,
};

[Stable]
struct OemCryptoPstReport {
  array<uint8, 20> signature;
  uint8 status;
  uint8 clock_security_level;
  uint64 seconds_since_license_received;
  uint64 seconds_since_first_decrypt;
  uint64 seconds_since_last_decrypt;
};

[Stable, Extensible]
enum OemCryptoRsaPaddingScheme {
  SIGN_RSASSA_PSS = 1,
  SIGN_PKCS1_BLOCK1 = 2,
};

[Stable, Extensible]
enum OemCryptoHdcpCapability {
  HDCP_NONE = 0,
  HDCP_V1   = 1,
  HDCP_V2   = 2,
  HDCP_V2_1 = 3,
  HDCP_V2_2 = 4,
  HDCP_V2_3 = 5,
  HDCP_NO_DIGITAL_OUTPUT = 0xFF,
};

[Stable, Extensible]
enum OemCryptoProvisioningMethod {
  PROVISIONING_ERROR = 0,
  DRM_CERTIFICATE = 1,
  KEYBOX = 2,
  OEM_CERTIFICATE = 3,
};

[Stable, Extensible]
enum OemCryptoPrivateKey {
  RSA_PRIVATE_KEY = 0,
  ECC_PRIVATE_KEY = 1,
};

[Stable]
struct SubSampleDescription {
  uint32 num_bytes_clear;
  uint32 num_bytes_encrypted;
  uint8 subsample_flags;
  uint32 block_offset;
};

// This is the interface that implements all the calls that map to the
// OEMCrypto API itself.
// Next method ID: 77
[Stable, Uuid="ed3807bc-7bce-472d-be4f-68774e613ace"]
interface OemCryptoService {
  InitializeDeprecated@0() => (OemCryptoResult result);
  [MinVersion=2] Initialize@36(uint32 oemcrypto_version)
      => (OemCryptoResult result);
  Terminate@1() => (OemCryptoResult result);
  OpenSession@2() => (OemCryptoResult result, uint32 session);
  CloseSession@3(uint32 session) => (OemCryptoResult result);
  GenerateDerivedKeys@4(uint32 session, array<uint8> mac_key_context,
                        array<uint8> enc_key_context)
      => (OemCryptoResult result);
  GenerateNonce@5(uint32 session) => (OemCryptoResult result, uint32 nonce);
  GenerateSignature@6(uint32 session, array<uint8> message)
      => (OemCryptoResult result, array<uint8>? signature);
  // The offset values are offsets into the message parameter for those values.
  // If they have a length and it's zero, then they are NULL; if there is no
  // length param then a bool param is there to indicate presence.
  LoadKeysV11OrV12@7(uint32 session, array<uint8> message,
                     array<uint8> signature, bool has_enc_mac_keys,
                     uint32 enc_mac_keys_iv_offset,
                     uint32 enc_mac_keys_offset,
                     array<OemCryptoKeyObjectV14> key_array,
                     uint32 pst_offset, uint32 pst_length)
      => (OemCryptoResult result);
  RefreshKeysV14@8(uint32 session, array<uint8> message,
                   array<uint8> signature,
                   array<OemCryptoKeyRefreshObjectV14> key_array)
      => (OemCryptoResult result);
  QueryKeyControl@9(uint32 session, array<uint8> key_id)
      => (OemCryptoResult result, array<uint8>? key_control_block);
  SelectKeyV13@10(uint32 session, array<uint8> key_id)
      => (OemCryptoResult result);
  DecryptCencV15@11(uint32 session, array<uint8> data, bool is_encrypted,
                    array<uint8, 16> iv, uint32 block_offset,
                    OemCryptoSecureBuffer? secure_buffer,
                    OemCryptoCencEncryptPatternDesc pattern)
      => (OemCryptoResult result, array<uint8>? decrypted_data);
  GenericEncrypt@12(uint32 session, array<uint8> data, array<uint8, 16> iv,
                    OemCryptoAlgorithm algorithm) =>
                    (OemCryptoResult result, array<uint8>? encrypted_data);
  GenericDecrypt@13(uint32 session, array<uint8> data, array<uint8, 16> iv,
                    OemCryptoAlgorithm algorithm) =>
                    (OemCryptoResult result, array<uint8>? decrypted_data);
  GenericSign@14(uint32 session, array<uint8> data,
                 OemCryptoAlgorithm algorithm) =>
                 (OemCryptoResult result, array<uint8>? signature);
  GenericVerify@15(uint32 session, array<uint8> data,
                   OemCryptoAlgorithm algorithm, array<uint8> signature) =>
                  (OemCryptoResult result);
  CopyBufferV14@16(array<uint8> data, OemCryptoSecureBuffer out_buffer)
      => (OemCryptoResult result);
  LoadTestKeyboxV13@17() => (OemCryptoResult result);
  IsRootKeyCertificateValid@18() => (OemCryptoResult result);
  GetDeviceId@19() => (OemCryptoResult result, array<uint8>? device_id);
  GetKeyData@20() => (OemCryptoResult result, array<uint8>? key_data);
  GetRandom@21(uint32 length) => (OemCryptoResult result, array<uint8>? data);
  GetNumberOfOpenSessions@22() => (OemCryptoResult result, uint32 num);
  GetMaxNumberOfSessions@23() => (OemCryptoResult result, uint32 max);
  RewrapDeviceRsaKey@24(uint32 session, array<uint8> message,
                        array<uint8> signature, uint32 nonce_offset,
                        uint32 enc_rsa_key_offset, uint32 enc_rsa_key_length,
                        uint32 enc_rsa_key_iv_offset)
      => (OemCryptoResult result, array<uint8>? wrapped_key);
  LoadDeviceRsaKey@25(uint32 session, array<uint8> wrapped_rsa_key)
      => (OemCryptoResult result);
  GenerateRsaSignature@26(uint32 session, array<uint8> message,
                          OemCryptoRsaPaddingScheme padding_scheme)
      => (OemCryptoResult result, array<uint8>? signature);
  DeriveKeysFromSessionKey@27(uint32 session, array<uint8> enc_session_key,
                              array<uint8> mac_key_context,
                              array<uint8> enc_key_context)
      => (OemCryptoResult result);
  SecurityPatchLevel@28() => (uint8 security_patch_level);
  GetHdcpCapability@29() => (OemCryptoResult result,
                             OemCryptoHdcpCapability current,
                             OemCryptoHdcpCapability maximum);
  UpdateUsageTable@30() => (OemCryptoResult result);
  DeactivateUsageEntryV12@31(array<uint8> pst) => (OemCryptoResult result);
  ReportUsage@32(uint32 session, array<uint8> pst)
      => (OemCryptoResult result, OemCryptoPstReport? report);
  DeleteUsageEntry@33(uint32 session, uint32 pst_offset, uint32 pst_length,
                      array<uint8> message, array<uint8> signature) =>
                      (OemCryptoResult result);
  ForceDeleteUsageEntry@34(array<uint8> pst) => (OemCryptoResult result);
  DeleteOldUsageTable@35() => (OemCryptoResult result);
  [MinVersion=2] GetProvisioningMethod@37()
      => (OemCryptoProvisioningMethod result);
  [MinVersion=2] SupportedCertificates@38() => (uint32 result);
  [MinVersion=2] IsSrmUpdateSupported@39() => (bool result);
  [MinVersion=2] GetCurrentSrmVersion@40()
      => (OemCryptoResult result, uint16 version);
  [MinVersion=2] LoadSrm@41(array<uint8> buffer) => (OemCryptoResult result);
  [MinVersion=2] RemoveSrm@42() => (OemCryptoResult result);
  // |avail_header_length| is the buffer size this was called with from Android.
  // We need to specify that so we know if we can complete this call for real or
  // instead just need to return the needed buffer size because execution of
  // this call has side effects.
  [MinVersion=2] CreateUsageTableHeader@43(uint32 avail_header_length)
      => (OemCryptoResult result, array<uint8>? header);
  [MinVersion=2] LoadUsageTableHeader@44(array<uint8> buffer)
      => (OemCryptoResult result);
  [MinVersion=2] CreateNewUsageEntry@45(uint32 session)
      => (OemCryptoResult result, uint32 usage_entry_number);
  [MinVersion=2] LoadUsageEntry@46(uint32 session, uint32 index,
                                   array<uint8> buffer) =>
                                   (OemCryptoResult result);
  // |avail_header_length| and |avail_entry_length| are the buffer sizes this
  // was called with from Android. We need to specify that so we know if we can
  // complete this call for real or instead just need to return the needed
  // buffer size because execution of this call has side effects.
  [MinVersion=2] UpdateUsageEntry@47(uint32 session, uint32 avail_header_length,
                                     uint32 avail_entry_length)
      => (OemCryptoResult result, array<uint8>? header, array<uint8>? entry);
  [MinVersion=2] DeactivateUsageEntry@48(uint32 session, array<uint8> pst)
      => (OemCryptoResult result);
  // |avail_header_length| is the buffer size this was called with from Android.
  // We need to specify that so we know if we can complete this call for real or
  // instead just need to return the needed buffer size because execution of
  // this call has side effects.
  [MinVersion=2] ShrinkUsageTableHeader@49(uint32 new_entry_count,
                                           uint32 avail_header_length)
      => (OemCryptoResult result, array<uint8>? header);
  [MinVersion=2] MoveEntry@50(uint32 session, uint32 new_index)
      => (OemCryptoResult result);
  [MinVersion=2] CopyOldUsageEntry@51(uint32 session, array<uint8> pst)
      => (OemCryptoResult result);
  [MinVersion=2] CreateOldUsageEntry@52(uint64 time_since_license_received,
                                        uint64 time_since_first_decrypt,
                                        uint64 time_since_last_decrypt,
                                        OemCryptoUsageEntryStatus status,
                                        array<uint8> server_mac_key,
                                        array<uint8> client_mac_key,
                                        array<uint8> pst) =>
                                        (OemCryptoResult result);
  [MinVersion=2] GetAnalogOutputFlags@53() => (uint32 result);
  [MinVersion=2] LoadTestKeybox@54(array<uint8> buffer) =>
                                   (OemCryptoResult result);
  [MinVersion=2]
  LoadEntitledContentKeysV14@55(
      uint32 session, array<OemCryptoEntitledContentKeyObjectV14> key_array)
      => (OemCryptoResult result);
  [MinVersion=2] SelectKey@56(uint32 session, array<uint8> content_key_id,
                              OemCryptoCipherMode cipher_mode) =>
                              (OemCryptoResult result);
  [MinVersion=2] LoadKeysV14@57(uint32 session, array<uint8> message,
                                 array<uint8> signature, bool has_enc_mac_keys,
                                 uint32 enc_mac_keys_iv_offset,
                                 uint32 enc_mac_keys_offset,
                                 array<OemCryptoKeyObjectV14> key_array,
                                 uint32 pst_offset, uint32 pst_length,
                                 array<uint8> srm_requirement,
                                 OemCryptoLicenseType license_type) =>
                             (OemCryptoResult result);
  [MinVersion=3] LoadKeys@58(uint32 session, array<uint8> message,
                             array<uint8> signature,
                             OemCryptoSubstring enc_mac_keys_iv,
                             OemCryptoSubstring enc_mac_keys,
                             array<OemCryptoKeyObject> key_array,
                             OemCryptoSubstring pst,
                             OemCryptoSubstring srm_restriction_data,
                             OemCryptoLicenseType license_type) =>
                         (OemCryptoResult result);
  [MinVersion=3] ResourceRatingTier@59() => (uint32 rating_tier);
  [MinVersion=3] BuildInformation@60() => (string build_information);
  [MinVersion=3] RefreshKeys@61(uint32 session, array<uint8> message,
                                array<uint8> signature,
                                array<OemCryptoKeyRefreshObject> key_array)
                         => (OemCryptoResult result);
  [MinVersion=3] LoadEntitledContentKeys@62(
      uint32 session, array<uint8> message,
      array<OemCryptoEntitledContentKeyObject> key_array)
      => (OemCryptoResult result);
  [MinVersion=4] GetOemPublicCertificate@63()
      => (OemCryptoResult result, array<uint8>? public_cert);
  [MinVersion=4] MaximumUsageTableHeaderSize@64() => (uint32 size);
  [MinVersion=4] IsAntiRollbackHwPresent@65() => (bool result);
  [MinVersion=4] MinorApiVersion@66() => (uint32 version);
  [MinVersion=4] PrepAndSignLicenseRequest@67(uint32 session,
                                              array<uint8> message,
                                              uint32 core_message_size,
                                              uint32 avail_signature_size)
      => (OemCryptoResult result, uint32 core_message_size,
          array<uint8>? message, array<uint8>? signature);
  [MinVersion=4] PrepAndSignRenewalRequest@68(uint32 session,
                                              array<uint8> message,
                                              uint32 core_message_size,
                                              uint32 avail_signature_size)
      => (OemCryptoResult result, uint32 core_message_size,
          array<uint8>? message, array<uint8>? signature);
  [MinVersion=4] PrepAndSignProvisioningRequest@69(uint32 session,
                                                   array<uint8> message,
                                                   uint32 core_message_size,
                                                   uint32 avail_signature_size)
      => (OemCryptoResult result, uint32 core_message_size,
          array<uint8>? message, array<uint8>? signature);
  [MinVersion=4] LoadLicense@70(uint32 session, array<uint8> message,
                                uint32 core_message_length,
                                array<uint8> signature)
      => (OemCryptoResult result);
  [MinVersion=4] LoadRenewal@71(uint32 session, array<uint8> message,
                                uint32 core_message_length,
                                array<uint8> signature)
      => (OemCryptoResult result);
  [MinVersion=4] LoadProvisioning@72(uint32 session, array<uint8> message,
                                     uint32 core_message_length,
                                     array<uint8> signature,
                                     uint32 avail_wrapped_private_key_size)
      => (OemCryptoResult result, array<uint8>? wrapped_private_key);
  [MinVersion=4] LoadOemPrivateKey@73(uint32 session)
      => (OemCryptoResult result);
  [MinVersion=4] LoadDrmPrivateKey@74(uint32 session,
                                      OemCryptoPrivateKey key_type,
                                      array<uint8> wrapped_private_key)
      => (OemCryptoResult result);
  // For decrypting to a secure buffer, pass in the secure_buffer parameter,
  // otherwise it will return the contents decrypted into a clear buffer in the
  // returned array. It will only do that if the drm policy allows it.
  [MinVersion=4] DecryptCenc@75(uint32 session, array<uint8> data,
                                array<uint8, 16> iv,
                                array<SubSampleDescription> sub_samples,
                                OemCryptoCencEncryptPatternDesc pattern,
                                OemCryptoSecureBuffer? secure_buffer)
      => (OemCryptoResult result, array<uint8>? decrypted_data);
  [MinVersion=5] CopyBuffer@76(uint32 session, array<uint8> data,
                               OemCryptoSecureBuffer out_buffer,
                               uint8 subsample_flags)
      => (OemCryptoResult result);
};

// OemCryptoService is implemented as another service outside of the Browser
// process, so we need to proxy a connection to it through ArcBridge initially.
// This interface is implemented in the Browser process and also in the daemon
// that runs in Chrome OS.
// Next Method ID: 1
interface OemCryptoHost {
  Connect@0(pending_receiver<OemCryptoService> oemcryptor);
};

// OemCryptoInstance is implemented in the liboemcrypto.so library that runs in
// Android and handles the Android side of the ArcBridge connection.
// Deprecated method IDs: 0
// Next Method ID: 2
interface OemCryptoInstance {
  // Establishes full-duplex communication with the host.
  [MinVersion=1] Init@1(pending_remote<OemCryptoHost> host_remote) => ();
};