diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..64cbc9b
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,41 @@
+// -----------------------------------------------------------------------------
+// CAS top level makefile
+//
+
+subdirs = ["wvutil", "protos", "plugin"]
+
+// -----------------------------------------------------------------------------
+// Builds libwvmediacas.so
+// Generates *.a, *.pb.h and *.pb.cc for *.proto files.
+//
+cc_library_shared {
+
+ name: "libwvmediacas",
+
+ proprietary: true,
+ relative_install_path: "mediacas",
+
+ shared_libs: [
+ "libcrypto",
+ "libcutils",
+ "liblog",
+ "libprotobuf-cpp-lite",
+ "libutils",
+ "libhidlbase",
+ ],
+
+ header_libs: ["media_plugin_headers"],
+
+ static_libs: [
+ "//vendor/widevine/libwvmediacas/protos:libcas_protos",
+ "//vendor/widevine/libwvmediacas/wvutil:libcasutil",
+ ],
+
+ whole_static_libs: [
+ "//vendor/widevine/libwvmediacas/plugin:libwvcasplugins",
+ ],
+
+ proto: {
+ type: "lite",
+ },
+}
diff --git a/README b/README
index e69de29..01214e0 100644
--- a/README
+++ b/README
@@ -0,0 +1 @@
+This repo contains Widevine MediaCas client code that works with Android U.
diff --git a/oemcrypto/Android.bp b/oemcrypto/Android.bp
new file mode 100644
index 0000000..7617298
--- /dev/null
+++ b/oemcrypto/Android.bp
@@ -0,0 +1,5 @@
+cc_library_headers {
+ name: "oemcastroheaders",
+ export_include_dirs: ["include"],
+ proprietary: true,
+}
diff --git a/oemcrypto/include/OEMCryptoCENC.h b/oemcrypto/include/OEMCryptoCENC.h
new file mode 100644
index 0000000..7a10cfc
--- /dev/null
+++ b/oemcrypto/include/OEMCryptoCENC.h
@@ -0,0 +1,5869 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+/**
+ * @mainpage OEMCrypto API v18.4
+ *
+ * OEMCrypto is the low level library implemented by the OEM to provide key and
+ * content protection, usually in a separate secure memory or process space. The
+ * term *OEMCrypto* refers to both the API described here and the library
+ * implementing the API.
+ *
+ * For an overview of OEMCrypto functionality, please see
+ * [Widevine Modular DRM Security Integration Guide for Common
+ * Encryption](../index)
+ *
+ * The OEMCrypto API is divided into several sections.
+ *
+ * @defgroup initcontrol Initialization and Control API
+ * Initialization and set up OEMCrypto.
+ *
+ * @defgroup keyladder Crypto Key Ladder API
+ * The crypto key ladder is a mechanism for staging crypto keys for use by the
+ * hardware crypto engine.
+ *
+ * Keys are always encrypted for transmission. Before
+ * a key can be used, it must be decrypted (typically using the top key in the
+ * key ladder) and then added to the key ladder for upcoming decryption
+ * operations. The Crypto Key Ladder API requires the device to provide
+ * hardware support for AES-128 CTR and CBC modes and prevent clear keys from
+ * being exposed to the insecure OS.
+ *
+ * @defgroup decryption Decryption API
+ * Devices that implement the Key Ladder API must also support a secure decode
+ * or secure decode and rendering implementation.
+ *
+ * This can be done by either
+ * decrypting into buffers secured by hardware protections and providing these
+ * secured buffers to the decoder/renderer or by implementing decrypt operations
+ * in the decoder/renderer.
+ *
+ * In a Security Level 2 implementation where the video path is not protected,
+ * the audio and video streams are decrypted using OEMCrypto_DecryptCENC() and
+ * buffers are returned to the media player in the clear.
+ *
+ * Generic Modular DRM allows an application to encrypt, decrypt, sign and
+ * verify arbitrary user data using a content key. This content key is
+ * securely delivered from the server to the client device using the same
+ * factory installed root of trust as a media content keys.
+ *
+ *
+ * 
+ *
+ * 
+ *
+ * 
+ *
+ * @defgroup factory_provision Factory Provisioning API
+ * Functions that are used to install the root of trust. This could be either a
+ * keybox or an OEM Certificate.
+ *
+ * Widevine keyboxes are used to establish a root of trust to secure content on
+ * a device that uses Provisioning 2.0. OEM Certificates are used to establish
+ * a root of trust to secure content on a device that uses Provisioning
+ * 3.0. Factory Provisioning a device is related to manufacturing methods. This
+ * section describes the API that installs the Widevine Keybox and the
+ * recommended methods for the OEM's factory provisioning procedure.
+ *
+ * Devices should support both a production keybox and a temporary test
+ * keybox. The production keybox is usually installed in the factory, or using
+ * OEMCrypto_WrapKeyboxOrOEMCert() and OEMCrypto_InstallKeyboxOrOEMCert(). The
+ * temporary keybox is a test keybox, and is loaded via
+ * OEMCrypto_LoadTestKeybox() by the unit tests. The test keybox will only be
+ * used temporarily while the unit tests are running, and will not be used by
+ * the general public. After the unit tests have been run, and
+ * OEMCrypto_Terminate() has been called, the production keybox should be active
+ * again.
+ *
+ * API functions marked as optional may be used by the OEM's factory
+ * provisioning procedure and implemented in the library, but are not called
+ * from the Widevine DRM Plugin during normal operation.
+ *
+ * @defgroup keybox Keybox and Provisioning 2.0 API
+ * Functions that are needed to for a device with a keybox.
+ *
+ * The OEMCrypto API allows for a device to be initially provisioned with a
+ * keybox or with an OEM certificate. See the section
+ * [Provisioning](../../index#provisioning) in the integration guide. In a
+ * Level 1 or Level 2 implementation, only the security processor may access the
+ * keys in the keybox. The following functions are for devices that are
+ * provisioned with a keybox, i.e. Provisioning 2.0.
+ *
+ * @defgroup oem_cert OEM Certificate and Provisioning 3.0 API
+ * Functions that are needed to for a device with an OEM Certificate.
+ *
+ * The OEMCrypto API allows for a device to be initially provisioned with a
+ * keybox or with an OEM certificate. See the section
+ * Provisioning in the integration guide.
+ * The functions in this section are for devices that are provisioned with an
+ * OEM Certificate, i.e. Provisioning 3.0.
+ *
+ * API functions marked as optional may be used by the OEM's factory
+ * provisioning procedure and implemented in the library, but are not called
+ * from the Widevine DRM Plugin during normal operation.
+ *
+ * @defgroup prov40 OEM Certificate and Provisioning 4.0 API
+ * Functions that are needed process a boot chain certificate.
+ *
+ * The OEMCrypto API allows for a device to be initially provisioned with a
+ * keybox or with an OEM certificate in the factory, or to use a boot chain
+ * derived by the device using a device specific key.
+ * See the section Provisioning
+ * in the integration guide.
+ * The functions in this section are for devices that are provisioned with a
+ * boot chain, i.e. Provisioning 4.0.
+ *
+ * @defgroup validation Validation and Feature Support API
+ * The OEMCrypto API is flexible enough to allow different devices to support
+ * different features. This section has functions that specify the level of
+ * support for various features. These values are reported to either the
+ * application or the license server.
+ *
+ * @defgroup drm_cert DRM Certificate Provisioning API
+ * This section of functions are used to provision the device with a DRM
+ * certificate. This certificate is obtained by a device in the field from a
+ * Google/Widevine provisioning server, or from a third party server running the
+ * Google/Widevine provisioning server SDK. Since the DRM certificate may be
+ * origin or application specific, a device may have several DRM certificates
+ * installed at a time. The DRM certificate is used to authenticate the device
+ * to a license server. In order to obtain a DRM certificate from a
+ * provisioning server, the device may authenticate itself using a keybox or
+ * using an OEM certificate.
+ *
+ * @defgroup usage_table Usage Table API
+ * The usage table is used to store license usage and allows a persistent
+ * license to be reloaded.
+ *
+ * @defgroup entitled Entitlement License API
+ * Functions that are needed for entitled and entitlement licenses.
+ *
+ * [Entitlement licensing](../../index#entitlement) is a way to provide access
+ * to content keys that may be stored elsewhere, such as in the content itself.
+ * This can be used to implement content key rotation without requiring new
+ * licenses, or access to multiple pieces of content with a single license.
+ *
+ * @defgroup test_verify Test and Verification API
+ * Functions that are designed to help test OEMCrypto and the device. They are
+ * not used during normal operation. Some functions, like those that test the
+ * full decrypt data path may be supported on a production device with no added
+ * risk of security loss.
+ *
+ * The following functions are used just for testing and verification of
+ * OEMCrypto and the CDM code.
+ *
+ * @defgroup common_types Common Types
+ * Enumerations and structures that are used by several OEMCrypto and ODK
+ * functions.
+ */
+
+#ifndef OEMCRYPTO_CENC_H_
+#define OEMCRYPTO_CENC_H_
+
+#include
+#include
+#include
+
+#include "OEMCryptoCENCCommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @addtogroup keyladder
+/// @{
+
+/// This is the internal session identifier.
+typedef uint32_t OEMCrypto_SESSION;
+
+/// @}
+
+/// @addtogroup decryption
+/// @{
+/**
+ * The memory referenced by OEMCrypto_SharedMemory* is safe to be placed in
+ * shared memory. The only data that should be placed into shared
+ * memory is the contents of input/output buffers, i.e. data that will
+ * not introduce security vulnerabilities if it is subject to
+ * modification while being accessed.
+ */
+typedef uint8_t OEMCrypto_SharedMemory;
+
+/** Specifies destination buffer type.
+ */
+typedef enum OEMCryptoBufferType {
+ OEMCrypto_BufferType_Clear,
+ OEMCrypto_BufferType_Secure,
+ OEMCrypto_BufferType_Direct,
+ OEMCrypto_BufferType_MaxValue = OEMCrypto_BufferType_Direct,
+} OEMCryptoBufferType;
+
+/**
+ * This structure is used as parameters in the OEMCrypto_DecryptCENC() and
+ * OEMCrypto_CopyBuffer() functions. This describes the type and access
+ * information for the memory to receive decrypted data.
+ *
+ * The OEMCrypto API supports a range of client device architectures. Different
+ * architectures have different methods for acquiring and securing buffers that
+ * will hold portions of the audio or video stream after decryption. Three basic
+ * strategies are recognized for handling decrypted stream data:
+ *
+ * 1. Return the decrypted data in the clear into normal user memory
+ * (ClearBuffer). The caller uses normal memory allocation methods to
+ * acquire a buffer, and supplies the memory address of the buffer in
+ * the descriptor.
+ * 2. Place the decrypted data into protected memory (SecureBuffer). The
+ * caller uses a platform-specific method to acquire the protected
+ * buffer and a user-memory handle that references it. The handle is
+ * supplied to the decrypt call in the descriptor. If the buffer is
+ * filled with several OEMCrypto calls, the same handle will be used,
+ * and the offset will be incremented to indicate where the next write
+ * should take place.
+ * 3. Place the decrypted data directly into the audio or video decoder
+ * fifo (Direct). The caller will use platform-specific methods to
+ * initialize the fifo and the decoders. The decrypted stream data is
+ * not accessible to the caller. This is used on some platforms only.
+ *
+ * @param[in] type: A tag that indicates which variant of the union is valid for
+ * this instance of the structure. [variant] clear: This variant is valid
+ * when the type is OEMCrypto_BufferType_Clear. This OEMCrypto_DestBufferDesc
+ * indicates output should be written to a clear buffer.
+ * @param[in] clear_buffer: A pointer to the address in memory to begin writing
+ * output.
+ * @param[in] clear_buffer_length: The length of the buffer that is available to
+ * contain output. [variant] secure: This variant is valid when the type is
+ * OEMCrypto_BufferType_Secure. This OEMCrypto_DestBufferDesc indicates
+ * output should be written to a secure buffer. The decrypted output must
+ * never leave the secure area until it is output from the device.
+ * @param[in] secure_buffer: An opaque handle to a secure buffer. The meaning of
+ * this handle is platform-specific.
+ * @param[in] secure_buffer_length: The length of the data contained in the
+ * secure buffer.
+ * @param[in] offset: An offset indicating where in the secure buffer to start
+ * writing data. [variant] direct: This variant is valid when the type is
+ * OEMCrypto_BufferType_Direct. This OEMCrypto_DestBufferDesc indicates
+ * output should be written directly to the decoder.
+ * @param[in] is_video: A flag indicating if the data is video and should be
+ * sent to the video decoder. If this is false, the data can be assumed to be
+ * audio and sent to the audio decoder.
+ *
+ * @version
+ * This struct changed in API version 16.
+ */
+typedef struct {
+ OEMCryptoBufferType type;
+ union {
+ struct { // type == OEMCrypto_BufferType_Clear
+ OEMCrypto_SharedMemory* clear_buffer;
+ size_t clear_buffer_length;
+ } clear;
+ struct { // type == OEMCrypto_BufferType_Secure
+ void* secure_buffer;
+ size_t secure_buffer_length;
+ size_t offset;
+ } secure;
+ struct { // type == OEMCrypto_BufferType_Direct
+ bool is_video;
+ } direct;
+ } buffer;
+} OEMCrypto_DestBufferDesc;
+
+/**
+ * This structure is used as parameters in the OEMCrypto_DecryptCENC() function.
+ *
+ * @param[in] input_data: An unaligned pointer to this sample from the stream.
+ * @param[in] input_data_length: The length of this sample in the stream, in
+ * bytes.
+ * @param[in] output_descriptor: A caller-owned descriptor that specifies the
+ * handling of the decrypted byte stream. See OEMCrypto_DestbufferDesc for
+ * details.
+ *
+ * @version
+ * This struct changed in API version 16.
+ */
+typedef struct {
+ const OEMCrypto_SharedMemory* input_data; // source for encrypted data.
+ size_t input_data_length; // length of encrypted data.
+ OEMCrypto_DestBufferDesc output_descriptor; // destination for clear data.
+} OEMCrypto_InputOutputPair;
+
+/**
+ * This structure is used as parameters in the OEMCrypto_DecryptCENC()
+ * function. In the DASH specification, a sample is composed of multiple
+ * samples, and each subsample is composed of two regions. The first region is
+ * clear unprotected data. We also call this clear data or unencrypted
+ * data. Immediately following the clear region is the protected region. The
+ * protected region is encrypted or encrypted with a pattern. The pattern and
+ * number of bytes that are encrypted in the protected region is discussed in
+ * this document when we talk about the function OEMCryptoDecryptCENC. For
+ * historic reasons, this document also calls the protected region the encrypted
+ * region.
+ *
+ * @param[in] num_bytes_clear: The number of unprotected bytes in this
+ * subsample. The clear bytes come before the encrypted bytes.
+ * @param[in] num_bytes_encrypted: The number of protected bytes in this
+ * subsample. The protected bytes come after the clear bytes.
+ * @param[in] subsample_flags: bitwise flags indicating if this is the first,
+ * middle, or last subsample in a sample. 1 = first subsample, 2 = last
+ * subsample, 3 = both first and last subsample, 0 = neither first nor last
+ * subsample.
+ * @param[in] block_offset: This will only be non-zero for the 'cenc' scheme.
+ * If it is non-zero, the decryption block boundary is different from the
+ * start of the data. block_offset should be subtracted from data to compute
+ * the starting address of the first decrypted block. The bytes between the
+ * decryption block start address and data are discarded after decryption. It
+ * does not adjust the beginning of the source or destination data. This
+ * parameter satisfies 0 <= block_offset < 16.
+ *
+ * @version
+ * This struct changed in API version 16.
+ */
+typedef struct {
+ size_t num_bytes_clear;
+ size_t num_bytes_encrypted;
+ uint8_t subsample_flags; // is this the first/last subsample in a sample?
+ size_t block_offset; // used for CTR "cenc" mode only.
+} OEMCrypto_SubSampleDescription;
+
+#define OEMCrypto_FirstSubsample 1
+#define OEMCrypto_LastSubsample 2
+
+/**
+ * This structure is used as parameters in the OEMCrypto_DecryptCENC() function.
+ *
+ * @param[in] buffers: A structure containing information about the input and
+ * output buffers.
+ * @param[in] iv: A 16-byte array containing the IV for the initial subsample of
+ * the sample.
+ * @param[in] subsamples: A caller-owned array of OEMCrypto_SubSampleDescription
+ * structures. Each entry in this array describes one subsample in the
+ * sample.
+ * @param[in] subsamples_length: The length of the array pointed to by the
+ * subsamples parameter.
+ *
+ * @version
+ * This struct changed in API version 16.
+ */
+typedef struct {
+ OEMCrypto_InputOutputPair buffers; // The source and destination buffers.
+ uint8_t iv[16]; // The IV for the initial subsample.
+ const OEMCrypto_SubSampleDescription* subsamples; // subsamples array.
+ size_t subsamples_length; // the number of subsamples in the sample.
+} OEMCrypto_SampleDescription;
+
+/**
+ * This structure is used as parameters in the OEMCrypto_DecryptCENC() function.
+ *
+ * Fields:
+ * @param[in] encrypt: The number of 16-byte crypto blocks to encrypt.
+ * @param[in] skip: The number of 16-byte crypto blocks to leave in the clear.
+ *
+ * @version
+ * This struct changed in API version 16.
+ */
+typedef struct {
+ size_t encrypt; // number of 16 byte blocks to decrypt.
+ size_t skip; // number of 16 byte blocks to leave in clear.
+} OEMCrypto_CENCEncryptPatternDesc;
+
+/**
+ * OEMCryptoCipherMode is used in OEMCrypto_GetKeyHandle() to prepare a key for
+ * decryption.
+ */
+typedef enum OEMCryptoCipherMode {
+ // explicit cipher modes used for modular DRM
+ OEMCrypto_CipherMode_CENC,
+ OEMCrypto_CipherMode_CBCS,
+ // cipher modes used for CAS
+ OEMCrypto_CipherMode_CTR,
+ OEMCrypto_CipherMode_CBC,
+ OEMCrypto_CipherMode_CSA2,
+ OEMCrypto_CipherMode_CSA3,
+ OEMCrypto_CipherMode_OFB,
+ OEMCrypto_CipherMode_SCTE,
+ OEMCrypto_CipherMode_ECB,
+ OEMCrypto_CipherMode_MaxValue = OEMCrypto_CipherMode_ECB,
+} OEMCryptoCipherMode;
+
+/**
+ * This is a list of valid algorithms for OEMCrypto_Generic_* functions.
+ * Some are valid for encryption/decryption, and some for signing/verifying.
+ */
+typedef enum OEMCrypto_Algorithm {
+ OEMCrypto_AES_CBC_128_NO_PADDING = 0,
+ OEMCrypto_HMAC_SHA256 = 1,
+ OEMCrypto_Algorithm_MaxValue = 1,
+} OEMCrypto_Algorithm;
+
+/// @}
+
+/// @addtogroup entitled
+/// @{
+/**
+ * Contains encrypted content key data for loading into the sessions keytable.
+ * The content key data is encrypted using AES-256-CBC encryption, with PKCS#7
+ * padding.
+
+ * @param entitlement_key_id: entitlement key id to be matched to key table.
+ * @param content_key_id: content key id to be loaded into key table.
+ * @param key_data_iv: the IV for performing AES-256-CBC decryption of the key
+ * data.
+ * @param key_data: encrypted content key data.
+ * @param content_iv: the IV for decrypting media content. Used by CAS only.
+ * @param cipher_mode: the encryption mode of the media content. Used by CAS
+ * only.
+ */
+typedef struct {
+ OEMCrypto_Substring entitlement_key_id;
+ OEMCrypto_Substring content_key_id;
+ OEMCrypto_Substring content_key_data_iv;
+ OEMCrypto_Substring content_key_data;
+ OEMCrypto_Substring content_iv;
+ OEMCryptoCipherMode cipher_mode;
+} OEMCrypto_EntitledContentKeyObject;
+
+/// @}
+
+/// @addtogroup usage_table
+/// @{
+
+#if 0 // If your compiler supports __attribute__((packed)).
+/**
+ * OEMCrypto_PST_Report is used to report an entry from the Usage Table.
+ *
+ * Platforms that have compilers that support packed structures, may use the
+ * following definition. Other platforms may use the header pst_report.h which
+ * defines a wrapper class.
+ *
+ * All fields are in network byte order.
+ */
+typedef struct {
+ uint8_t signature[20]; // -- HMAC SHA1 of the rest of the report.
+ uint8_t status; // current status of entry. (OEMCrypto_Usage_Entry_Status)
+ uint8_t clock_security_level;
+ uint8_t pst_length;
+ uint8_t padding; // make int64's word aligned.
+ int64_t seconds_since_license_received; // now - time_of_license_received
+ int64_t seconds_since_first_decrypt; // now - time_of_first_decrypt
+ int64_t seconds_since_last_decrypt; // now - time_of_last_decrypt
+ uint8_t pst[];
+} __attribute__((packed)) OEMCrypto_PST_Report;
+#endif
+
+/**
+ * Valid values for clock_security_level in OEMCrypto_PST_Report.
+ */
+typedef enum OEMCrypto_Clock_Security_Level {
+ kInsecureClock = 0,
+ kMonotonicClock = 1,
+ kSecureTimer = 1, // DEPRECATED. Do not use.
+ kSecureClock = 2,
+ kHardwareSecureClock = 3
+} OEMCrypto_Clock_Security_Level;
+
+typedef uint8_t RSA_Padding_Scheme;
+// RSASSA-PSS with SHA1.
+#define kSign_RSASSA_PSS ((RSA_Padding_Scheme)0x1)
+// PKCS1 with block type 1 padding (only).
+#define kSign_PKCS1_Block1 ((RSA_Padding_Scheme)0x2)
+
+/// @}
+
+/// @addtogroup validation
+/// @{
+/**
+ * OEMCrypto_HDCP_Capability is used in the key control block to enforce HDCP
+ * level, and in GetHDCPCapability for reporting.
+ */
+typedef enum OEMCrypto_HDCP_Capability {
+ HDCP_NONE = 0, // No HDCP supported, no secure data path.
+ HDCP_V1 = 1, // HDCP version 1.x
+ HDCP_V2 = 2, // HDCP version 2.0 Type 1.
+ HDCP_V2_1 = 3, // HDCP version 2.1 Type 1.
+ HDCP_V2_2 = 4, // HDCP version 2.2 Type 1.
+ HDCP_V2_3 = 5, // HDCP version 2.3 Type 1.
+ // For backwards compatibility, these values are added after the V2 fields.
+ // However, it is optional for devices and they can still report HDCP_V1.
+ HDCP_V1_0 = 6,
+ HDCP_V1_1 = 7,
+ HDCP_V1_2 = 8,
+ HDCP_V1_3 = 9,
+ HDCP_V1_4 = 10,
+ HDCP_NO_DIGITAL_OUTPUT = 0xff // No digital output.
+} OEMCrypto_HDCP_Capability;
+
+/**
+ * OEMCrypto_DTCP2_Capability is used in OEMCrypto_GetDTCP2Capability
+ * for reporting the level of DTCP2 support for a device.
+ */
+typedef enum OEMCrypto_DTCP2_Capability {
+ OEMCrypto_NO_DTCP2 = 0, // DTCP2 is not supported.
+ OEMCrypto_DTCP2_V1 = 1, // At least v1 of DTCP2 is supported.
+} OEMCrypto_DTCP2_Capability;
+
+/**
+ Return value for OEMCrypto_GetProvisioningMethod().
+ */
+typedef enum OEMCrypto_ProvisioningMethod {
+ OEMCrypto_ProvisioningError = 0, // Device cannot be provisioned.
+ // Device has baked in DRM certificate (level 3 only).
+ OEMCrypto_DrmCertificate = 1,
+ // Device has factory installed unique keybox.
+ OEMCrypto_Keybox = 2,
+ // Device has factory installed OEM certificate.
+ OEMCrypto_OEMCertificate = 3,
+ // Device has Boot Certificate Chain (BCC).
+ OEMCrypto_BootCertificateChain = 4,
+ // Device has baked in DRM certificate with reprovisioning (level 3 only).
+ OEMCrypto_DrmReprovisioning = 5
+} OEMCrypto_ProvisioningMethod;
+
+/**
+ Return value for OEMCrypto_GetWatermarkingSupport().
+ */
+typedef enum OEMCrypto_WatermarkingSupport {
+ OEMCrypto_WatermarkingError = 0,
+ OEMCrypto_WatermarkingNotSupported = 1,
+ OEMCrypto_WatermarkingConfigurable = 2,
+ OEMCrypto_WatermarkingAlwaysOn = 3,
+} OEMCrypto_WatermarkingSupport;
+
+/**
+ Return value for OEMCrypto_GetSignatureHashAlgorithm().
+ */
+typedef enum OEMCrypto_SignatureHashAlgorithm {
+ OEMCrypto_SHA1 = 0,
+ OEMCrypto_SHA2_256 = 1,
+ OEMCrypto_SHA2_384 = 2,
+ OEMCrypto_SHA2_512 = 3,
+} OEMCrypto_SignatureHashAlgorithm;
+
+/**
+ * Flags indicating public/private key types supported.
+ */
+#define OEMCrypto_Supports_RSA_2048bit 0x1
+#define OEMCrypto_Supports_RSA_3072bit 0x2
+#define OEMCrypto_Supports_RSA_CAST 0x10
+#define OEMCrypto_Supports_ECC_secp256r1 0x100
+#define OEMCrypto_Supports_ECC_secp384r1 0x200
+#define OEMCrypto_Supports_ECC_secp521r1 0x400
+
+/**
+ * Flags indicating full decrypt path hash supported.
+ */
+#define OEMCrypto_Hash_Not_Supported 0
+#define OEMCrypto_CRC_Clear_Buffer 1
+#define OEMCrypto_Partner_Defined_Hash 2
+
+/**
+ * Return values from OEMCrypto_GetAnalogOutputFlags.
+ */
+#define OEMCrypto_No_Analog_Output 0x0
+#define OEMCrypto_Supports_Analog_Output 0x1
+#define OEMCrypto_Can_Disable_Analog_Ouptput 0x2
+#define OEMCrypto_Supports_CGMS_A 0x4
+// Unknown_Analog_Output is used only for backwards compatibility.
+#define OEMCrypto_Unknown_Analog_Output (1 << 31)
+
+/// @}
+
+/**
+ * Obfuscation Renames.
+ *
+ * The function signatures of each oecc obfuscated name should remain static
+ * across multiple versions. When we want to change the function signature of a
+ * function, we will give the new signature a new oecc number and keep the
+ * original oecc name with the original function signature. This allows us to
+ * maintain backwards compatibility when the CDM loads an older version of
+ * liboemcrypto.so using dlopen.
+ */
+// clang-format off
+#define OEMCrypto_Initialize _oecc01
+#define OEMCrypto_Terminate _oecc02
+#define OEMCrypto_InstallKeybox _oecc03
+// Rename InstallKeybox to InstallKeyboxOrOEMCert.
+#define OEMCrypto_InstallRootKeyCertificate _oecc03
+#define OEMCrypto_InstallKeyboxOrOEMCert _oecc03
+#define OEMCrypto_GetKeyData _oecc04
+#define OEMCrypto_IsKeyboxValid _oecc05
+// Rename IsKeyboxValid to IsKeyboxOrOEMCertValid.
+#define OEMCrypto_IsRootKeyCertificateValid _oecc05
+#define OEMCrypto_IsKeyboxOrOEMCertValid _oecc05
+#define OEMCrypto_GetRandom _oecc06
+#define OEMCrypto_GetDeviceID _oecc07
+#define OEMCrypto_WrapKeybox _oecc08
+// Rename WrapKeybox to WrapKeyboxOrOEMCert
+#define OEMCrypto_WrapRootKeyCertificate _oecc08
+#define OEMCrypto_WrapKeyboxOrOEMCert _oecc08
+#define OEMCrypto_OpenSession _oecc09
+#define OEMCrypto_CloseSession _oecc10
+#define OEMCrypto_DecryptCTR_V10 _oecc11
+#define OEMCrypto_GenerateDerivedKeys_V15 _oecc12
+#define OEMCrypto_GenerateSignature _oecc13
+#define OEMCrypto_GenerateNonce _oecc14
+#define OEMCrypto_LoadKeys_V8 _oecc15
+#define OEMCrypto_RefreshKeys_V14 _oecc16
+#define OEMCrypto_SelectKey_V13 _oecc17
+#define OEMCrypto_RewrapDeviceRSAKey _oecc18
+#define OEMCrypto_LoadDeviceRSAKey _oecc19
+#define OEMCrypto_GenerateRSASignature_V8 _oecc20
+#define OEMCrypto_DeriveKeysFromSessionKey _oecc21
+#define OEMCrypto_APIVersion _oecc22
+#define OEMCrypto_SecurityLevel_V16 _oecc23
+#define OEMCrypto_Generic_Encrypt_V17 _oecc24
+#define OEMCrypto_Generic_Decrypt_V17 _oecc25
+#define OEMCrypto_Generic_Sign_V17 _oecc26
+#define OEMCrypto_Generic_Verify_V17 _oecc27
+#define OEMCrypto_GetHDCPCapability_V9 _oecc28
+#define OEMCrypto_SupportsUsageTable _oecc29
+#define OEMCrypto_UpdateUsageTable _oecc30
+#define OEMCrypto_DeactivateUsageEntry_V12 _oecc31
+#define OEMCrypto_ReportUsage _oecc32
+#define OEMCrypto_DeleteUsageEntry _oecc33
+#define OEMCrypto_DeleteOldUsageTable _oecc34
+#define OEMCrypto_LoadKeys_V9_or_V10 _oecc35
+#define OEMCrypto_GenerateRSASignature _oecc36
+#define OEMCrypto_GetMaxNumberOfSessions _oecc37
+#define OEMCrypto_GetNumberOfOpenSessions _oecc38
+#define OEMCrypto_IsAntiRollbackHwPresent _oecc39
+#define OEMCrypto_CopyBuffer_V14 _oecc40
+#define OEMCrypto_QueryKeyControl _oecc41
+#define OEMCrypto_LoadTestKeybox_V13 _oecc42
+#define OEMCrypto_ForceDeleteUsageEntry _oecc43
+#define OEMCrypto_GetHDCPCapability _oecc44
+#define OEMCrypto_LoadTestRSAKey _oecc45
+#define OEMCrypto_Security_Patch_Level _oecc46
+#define OEMCrypto_LoadKeys_V11_or_V12 _oecc47
+#define OEMCrypto_DecryptCENC_V15 _oecc48
+#define OEMCrypto_GetProvisioningMethod _oecc49
+#define OEMCrypto_GetOEMPublicCertificate_V15 _oecc50
+#define OEMCrypto_RewrapDeviceRSAKey30 _oecc51
+#define OEMCrypto_SupportedCertificates _oecc52
+#define OEMCrypto_IsSRMUpdateSupported _oecc53
+#define OEMCrypto_GetCurrentSRMVersion _oecc54
+#define OEMCrypto_LoadSRM _oecc55
+#define OEMCrypto_LoadKeys_V13 _oecc56
+#define OEMCrypto_RemoveSRM _oecc57
+#define OEMCrypto_CreateUsageTableHeader _oecc61
+#define OEMCrypto_LoadUsageTableHeader _oecc62
+#define OEMCrypto_CreateNewUsageEntry _oecc63
+#define OEMCrypto_LoadUsageEntry _oecc64
+#define OEMCrypto_UpdateUsageEntry _oecc65
+#define OEMCrypto_DeactivateUsageEntry _oecc66
+#define OEMCrypto_ShrinkUsageTableHeader _oecc67
+#define OEMCrypto_MoveEntry _oecc68
+#define OEMCrypto_CopyOldUsageEntry _oecc69
+#define OEMCrypto_CreateOldUsageEntry _oecc70
+#define OEMCrypto_GetAnalogOutputFlags _oecc71
+#define OEMCrypto_LoadTestKeybox _oecc78
+#define OEMCrypto_LoadEntitledContentKeys_V14 _oecc79
+#define OEMCrypto_SelectKey _oecc81
+#define OEMCrypto_LoadKeys_V14 _oecc82
+#define OEMCrypto_LoadKeys _oecc83
+#define OEMCrypto_SetSandbox _oecc84
+#define OEMCrypto_ResourceRatingTier _oecc85
+#define OEMCrypto_SupportsDecryptHash _oecc86
+#define OEMCrypto_InitializeDecryptHash _oecc87
+#define OEMCrypto_SetDecryptHash _oecc88
+#define OEMCrypto_GetHashErrorCode _oecc89
+#define OEMCrypto_BuildInformation_V16 _oecc90
+#define OEMCrypto_RefreshKeys _oecc91
+#define OEMCrypto_LoadEntitledContentKeys_V16 _oecc92
+#define OEMCrypto_CopyBuffer _oecc93
+#define OEMCrypto_MaximumUsageTableHeaderSize _oecc94
+#define OEMCrypto_GenerateDerivedKeys _oecc95
+#define OEMCrypto_PrepAndSignLicenseRequest _oecc96
+#define OEMCrypto_PrepAndSignRenewalRequest _oecc97
+#define OEMCrypto_PrepAndSignProvisioningRequest _oecc98
+#define OEMCrypto_LoadLicense _oecc99
+#define OEMCrypto_LoadRenewal _oecc101
+#define OEMCrypto_LoadProvisioning _oecc102
+#define OEMCrypto_LoadOEMPrivateKey _oecc103
+#define OEMCrypto_GetOEMPublicCertificate _oecc104
+#define OEMCrypto_DecryptCENC_V17 _oecc105
+#define OEMCrypto_LoadDRMPrivateKey _oecc107
+#define OEMCrypto_MinorAPIVersion _oecc108
+#define OEMCrypto_AllocateSecureBuffer _oecc109
+#define OEMCrypto_FreeSecureBuffer _oecc110
+#define OEMCrypto_CreateEntitledKeySession _oecc111
+#define OEMCrypto_RemoveEntitledKeySession _oecc112
+#define OEMCrypto_GenerateOTARequest _oecc113
+#define OEMCrypto_ProcessOTAKeybox _oecc114
+#define OEMCrypto_OPK_SerializationVersion _oecc115
+#define OEMCrypto_GetBootCertificateChain _oecc116
+#define OEMCrypto_GenerateCertificateKeyPair _oecc117
+#define OEMCrypto_InstallOemPrivateKey _oecc118
+#define OEMCrypto_ReassociateEntitledKeySession _oecc119
+#define OEMCrypto_LoadCasECMKeys _oecc120
+#define OEMCrypto_LoadEntitledContentKeys _oecc121
+#define OEMCrypto_ProductionReady _oecc122
+#define OEMCrypto_Idle _oecc123
+#define OEMCrypto_Wake _oecc124
+#define OEMCrypto_BuildInformation _oecc125
+#define OEMCrypto_SecurityLevel _oecc126
+#define OEMCrypto_ReuseUsageEntry _oecc127
+#define OEMCrypto_GetDTCP2Capability _oecc128
+#define OEMCrypto_GetWatermarkingSupport _oecc129
+#define OEMCrypto_GetOEMKeyToken _oecc130
+#define OEMCrypto_GetDeviceInformation _oecc131
+#define OEMCrypto_SetMaxAPIVersion _oecc132
+#define OEMCrypto_GetKeyHandle _oecc133
+#define OEMCrypto_DecryptCENC _oecc134
+#define OEMCrypto_Generic_Encrypt _oecc135
+#define OEMCrypto_Generic_Decrypt _oecc136
+#define OEMCrypto_Generic_Sign _oecc137
+#define OEMCrypto_Generic_Verify _oecc138
+#define OEMCrypto_GetSignatureHashAlgorithm _oecc139
+#define OEMCrypto_EnterTestMode _oecc140
+#define OEMCrypto_GetDeviceSignedCsrPayload _oecc141
+#define OEMCrypto_FactoryInstallBCCSignature _oecc142
+#define OEMCrypto_GetEmbeddedDrmCertificate _oecc143
+// clang-format on
+
+/// @addtogroup initcontrol
+/// @{
+/** Specifies whether system is in idle mode.
+ */
+typedef enum OEMCrypto_IdleState {
+ OEMCrypto_NoCryptoActivity = 0, // The system is not idle, but OEMCrypto is.
+ OEMCrypto_CpuSuspend = 1,
+} OEMCrypto_IdleState;
+
+/**
+ * This tells OEMCrypto which sandbox the current process belongs to. Any
+ * persistent memory used to store the generation number should be associated
+ * with this sandbox id. OEMCrypto can assume that this sandbox will be tied
+ * to the current process or VM until OEMCrypto_Terminate() is called. See the
+ * section [VM and Sandbox Support](../../index#sandbox) for more details.
+ *
+ * If OEMCrypto does not support sandboxes, it will return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED. On most platforms, this function will
+ * just return OEMCrypto_ERROR_NOT_IMPLEMENTED. If OEMCrypto supports
+ * sandboxes, this function returns OEMCrypto_SUCCESS on success, and
+ * OEMCrypto_ERROR_UNKNOWN_FAILURE on failure.
+ *
+ * The CDM layer will call OEMCrypto_SetSandbox() once before
+ * OEMCrypto_Initialize(). After this function is called and returns success,
+ * it will be OEMCrypto's responsibility to keep calls to usage table
+ * functions separate, and to accept a call to OEMCrypto_Terminate() for each
+ * sandbox.
+ *
+ * @param[in] sandbox_id: a short string unique to the current sandbox.
+ * @param[in] sandbox_id_length: length of sandbox_id.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED sandbox functionality not supported
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system. It is called once before
+ * OEMCrypto_Initialize().
+ *
+ * @version
+ * This method is new in version 15 of the API.
+ */
+OEMCryptoResult OEMCrypto_SetSandbox(const uint8_t* sandbox_id,
+ size_t sandbox_id_length);
+
+/**
+ * Initialize the crypto firmware/hardware.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is supported by all API versions.
+ */
+OEMCryptoResult OEMCrypto_Initialize(void);
+
+/**
+ * Specify the maximum OEMCrypto API version supported by the CDM layer above
+ * OEMCrypto. If OEMCrypto can support multiple versions then it must restrict
+ * itself to this version number. If OEMCrypto only supports one version, then
+ * it may ignore this function and return
+ * ERROR_NOT_IMPLEMENTED. OEMCrypto_SetMaxAPIVersion will be called after
+ * OEMCrypto_Initialize() and before any other functions.
+ *
+ * @param[in] max_version: the maximum version of OEMCrypto supported by CDM
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED function not implemented
+ * @retval other any other error
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 18.
+ */
+OEMCryptoResult OEMCrypto_SetMaxAPIVersion(uint32_t max_version);
+
+/**
+ * Closes the crypto operation and releases all related resources.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_TERMINATE_FAILED failed to de-initialize crypto
+ * hardware
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system. No other functions will be called before the
+ * system is re-initialized.
+ *
+ * @version
+ * This method is supported by all API versions.
+ */
+OEMCryptoResult OEMCrypto_Terminate(void);
+
+/**
+ * If possible, OEMCrypto may reduce power consumption or other resources. For
+ * example, it may be possible to reduce the CPU clock rates. When the system
+ * is in idle mode, then the CDM will not call OEMCrypto_GetHDCPCapability.
+ *
+ * This function is not required -- OEMCrypto may ignore this function. It is
+ * only used to improve performance. This function may return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED to indicate it is not supported.
+ *
+ * OEMCrypto_Idle may be called multiple times with no call to OEMCrypto_Wake
+ * in between. A call to OEMCrypto_Idle with different values of
+ * OEMCrypto_IdleState or os_specific_code may happen in any order. It is
+ * OEMCrypto’s responsibility to choose the appropriate behavior for improving
+ * power consumption. In particular, OEMCrypto may be notified of the
+ * OEMCrypto_NoCryptoActivity state before or after a notification of the
+ * OEMCrypto_CpuSuspend state, or OEMCrypto_NoCryptoActivity may not be notified
+ * at all. On some platforms, a call with OEMCrypto_CpuSuspend may never
+ * happen.
+ *
+ * The acceptable values of `os_specific_code` must be coordinated between the
+ * OS and the OEMCrypto vendor. On some platforms, for example Android, only
+ * the value of 0 will be used. For other platforms, it is the responsibility
+ * of the OEM device maker to coordinate with the SOC to define acceptable
+ * values of `os_specific_code`.
+ *
+ * @param[in] state: The idle state. This indicates if the call came from
+ * the OS or the CDM.
+ * @param[in] os_specific_code: Specified by the platform or OS for extra
+ * sleep information.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system. No other functions will be called before the
+ * system is re-initialized.
+ *
+ * @version
+ * This method is supported by all API versions.
+ */
+OEMCryptoResult OEMCrypto_Idle(OEMCrypto_IdleState state,
+ uint32_t os_specific_code);
+
+/**
+ * The new function OEMCrypto_Wake will be called to indicate that crypto
+ * operations will resume. A call to OEMCrypto_Wake after the system is already
+ * awake shall have no effect. If OEMCrypto cannot recover from being idle, it
+ * may return OEMCrypto_ERROR_SESSION_LOST_STATE or
+ * OEMCrypto_ERROR_SYSTEM_INVALIDATED.
+ *
+ * The CDM layer may postpone a call to OEMCrypto_Wake until Widevine activity
+ * is starting. This may happen long after the CPU wakes up.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system. No other functions will be called before the
+ * system is re-initialized.
+ *
+ * @version
+ * This method is supported by all API versions.
+ */
+OEMCryptoResult OEMCrypto_Wake(void);
+
+/// @}
+
+/// @addtogroup keyladder
+/// @{
+/**
+ * Open a new crypto security engine context. The security engine hardware
+ * and firmware shall acquire resources that are needed to support the
+ * session, and return a session handle that identifies that session in
+ * future calls.
+ *
+ * This function shall call ODK_InitializeSessionValues to initialize the
+ * session's clock values, timer values, and nonce values.
+ * ODK_InitializeSessionValues is described in the document "License Duration
+ * and Renewal", to initialize the session's clock values.
+ *
+ * @param[out] session: an opaque handle that the crypto firmware uses to
+ * identify the session.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_TOO_MANY_SESSIONS failed because too many sessions
+ * are open
+ * @retval OEMCrypto_ERROR_OPEN_SESSION_FAILED there is a resource issue or the
+ * security engine is not properly initialized.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Initialization Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock
+ * on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session);
+
+/**
+ * Closes the crypto security engine session and frees any associated
+ * resources. If this session is associated with a Usage Entry, all resident
+ * memory associated with it will be freed. It is the CDM layer's
+ * responsibility to call OEMCrypto_UpdateUsageEntry() before closing the
+ * session.
+ *
+ * @param[in] session: handle for the session to be closed.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION no open session with that id.
+ * @retval OEMCrypto_ERROR_CLOSE_SESSION_FAILED illegal/unrecognized handle or
+ * the security engine is not properly initialized.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Initialization Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock
+ * on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 13.
+ */
+OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session);
+
+/**
+ * Generates three secondary keys, mac_key[server], mac_key[client], and
+ * encrypt_key, for handling signing and content key decryption under the
+ * license server protocol for CENC.
+ *
+ * Refer to the Key Derivation section above for more details. This function
+ * computes the AES-128-CMAC of the enc_key_context and stores it in secure
+ * memory as the encrypt_key. It then computes four cycles of AES-128-CMAC of
+ * the mac_key_context and stores it in the mac_keys -- the first two cycles
+ * generate the mac_key[server] and the second two cycles generate the
+ * mac_key[client]. These two keys will be stored until the next call to
+ * OEMCrypto_LoadLicense(). The device key from the keybox is used as the key
+ * for the AES-128-CMAC.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] mac_key_context: pointer to memory containing context data for
+ * computing the HMAC generation key.
+ * @param[in] mac_key_context_length: length of the HMAC key context data, in
+ * bytes.
+ * @param[in] enc_key_context: pointer to memory containing context data for
+ * computing the encryption key.
+ * @param[in] enc_key_context_length: length of the encryption key context data,
+ * in bytes.
+ *
+ * Results:
+ * mac_key[server]: the 256 bit mac key is generated and stored in secure
+ * memory.
+ * mac_key[client]: the 256 bit mac key is generated and stored in secure
+ * memory.
+ * enc_key: the 128 bit encryption key is generated and stored in secure
+ * memory.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support mac_key_context and enc_key_context sizes as
+ * described in the section OEMCrypto_ResourceRatingTier() for messages. The
+ * key derivation context is about 25 bytes prepended to the request message.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffers are
+ * too large.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 12.
+ */
+OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
+ OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* mac_key_context,
+ size_t mac_key_context_length,
+ const OEMCrypto_SharedMemory* enc_key_context,
+ size_t enc_key_context_length);
+
+/**
+ * Generates three secondary keys, mac_key[server], mac_key[client] and
+ * encrypt_key, for handling signing and content key decryption under the
+ * license server protocol for CENC.
+ *
+ * This function is similar to OEMCrypto_GenerateDerivedKeys(), except that it
+ * uses a session key to generate the secondary keys instead of the Widevine
+ * Keybox device key. These three keys will be stored in secure memory until
+ * the next call to LoadLicense or LoadProvisioning.
+ *
+ * If the session's private key is an RSA key, then the session key is passed
+ * in encrypted by the device RSA public key as the derivation_key, and must
+ * be decrypted with the RSA private key before use.
+ *
+ * If the sesion's private key is an ECC key, then the session key is the
+ * SHA256 of the shared secret key calculated by ECDH between the device's
+ * ECC private key and the derivation_key. See the document "OEMCrypto
+ * Elliptic Curve Support" for details.
+ *
+ * Once the enc_key and mac_keys have been generated, all calls to
+ * OEMCrypto_LoadLicense() proceed in the same manner for license requests using
+ * RSA or using a Widevine keybox token.
+ *
+ * This function is also used to derive keys before processing a Cast
+ * Certificate provisioning response in OEMCrypto_LoadProvisioning().
+ * See [Cast Receiver](../../cast) for more details.
+ *
+ * @verification
+ * If the RSA key's allowed_schemes is not kSign_RSASSA_PSS, then no keys are
+ * derived and the error OEMCrypto_ERROR_INVALID_KEY is returned. An RSA
+ * key cannot be used for both deriving session keys and also for PKCS1
+ * signatures.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] derivation_key: session key, encrypted with the public RSA key
+ * (from the DRM certifcate) using RSA-OAEP.
+ * @param[in] derivation_key_length: length of derivation_key, in bytes.
+ * @param[in] mac_key_context: pointer to memory containing context data for
+ * computing the HMAC generation key.
+ * @param[in] mac_key_context_length: length of the HMAC key context data, in
+ * bytes.
+ * @param[in] enc_key_context: pointer to memory containing context data for
+ * computing the encryption key.
+ * @param[in] enc_key_context_length: length of the encryption key context data,
+ * in bytes.
+ *
+ * Results:
+ * mac_key[server]: the 256 bit mac key is generated and stored in secure
+ * memory.
+ * mac_key[client]: the 256 bit mac key is generated and stored in secure
+ * memory.
+ * enc_key: the 128 bit encryption key is generated and stored in secure
+ * memory.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support mac_key_context and enc_key_context sizes as
+ * described in the section OEMCrypto_ResourceRatingTier() for messages. The
+ * key derivation context is about 25 bytes prepended to the request message.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffers are
+ * too large.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
+ OEMCrypto_SESSION session, const uint8_t* derivation_key,
+ size_t derivation_key_length, const OEMCrypto_SharedMemory* mac_key_context,
+ size_t mac_key_context_length,
+ const OEMCrypto_SharedMemory* enc_key_context,
+ size_t enc_key_context_length);
+
+/**
+ * Generates a 32-bit nonce to detect possible replay attack on the key
+ * control block. The nonce is stored in secure memory and will be used in
+ * the license or provisioning request.
+ *
+ * Because the nonce will be used to prevent replay attacks, it is desirable
+ * that a rogue application cannot rapidly call this function until a
+ * repeated nonce is created randomly. This is called a nonce flood. With
+ * this in mind, if more than 200 nonces are requested within one second,
+ * OEMCrypto will return an error after the 200th and not generate any more
+ * nonces for the rest of the second. After an error, if the application
+ * waits at least one second before requesting more nonces, then OEMCrypto
+ * will reset the error condition and generate valid nonces again.
+ *
+ * The nonce should be stored in the session's ODK_NonceValue field by
+ * calling the function ODK_SetNonceValue(&nonce_values, nonce). The ODK
+ * functions are documented in "Widevine Core Message Serialization".
+ *
+ * This function shall only be called at most once per open session. It shall
+ * only be called before signing either a provisioning request or a license
+ * request. If an attempt is made to generate a nonce while in the wrong
+ * state, an error of OEMCrypto_ERROR_INVALID_CONTEXT is returned.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[out] nonce: pointer to memory to receive the computed nonce.
+ *
+ * Results:
+ * nonce: the nonce is also stored in secure memory.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Initialization Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock
+ * on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
+ uint32_t* nonce);
+
+/**
+ * OEMCrypto will use ODK_PrepareCoreLicenseRequest to prepare the core
+ * message. If it returns OEMCrypto_SUCCESS, then OEMCrypto shall sign the
+ * message body using the DRM certificate's private key. If it returns an
+ * error, the error should be returned by OEMCrypto to the CDM layer.
+ * ODK_PrepareCoreLicenseRequest is described in the document "Widevine Core
+ * Message Serialization".
+ *
+ * The message body is the buffer starting at message + core_message_size,
+ * and with length message_length - core_message_size. The reason OEMCrypto
+ * only signs the message body and not the entire message is to allow a v16
+ * device to request a license from a v15 license server.
+ *
+ * If the session's private RSA key has an "allowed_schemes" bit field, then
+ * it must be 0x1 (RSASSA-PSS with SHA1). If not, then an error of
+ * OEMCrypto_ERROR_SIGNATURE_FAILURE shall be returned.
+ *
+ * OEMCrypto shall also call the function ODK_InitializeClockValues,
+ * described in the document "License Duration and Renewal", to initialize
+ * the session's clock values.
+ *
+ * Refer to the Signing Messages Sent to a Server section above for more
+ * details about the signature algorithm.
+ *
+ * NOTE: if signature pointer is null and/or input signature_length is zero,
+ * this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
+ * signature_length to the size needed to receive the output signature.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in,out] message: Pointer to memory for the entire message. Modified by
+ * OEMCrypto via the ODK library.
+ * @param[in] message_length: length of the entire message buffer.
+ * @param[in,out] core_message_size: length of the core message at the beginning
+ * of the message. (in) size of buffer reserved for the core message, in
+ * bytes. (out) actual length of the core message, in bytes.
+ * @param[out] signature: pointer to memory to receive the computed signature.
+ * @param[in,out] signature_length: (in) length of the signature buffer, in
+ * bytes. (out) actual length of the signature, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if signature buffer is not large enough
+ * to hold the signature.
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_INVALID_KEY if the session's private key is not a
+ * DRM key.
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_PrepAndSignLicenseRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_size, uint8_t* signature, size_t* signature_length);
+
+/**
+ * OEMCrypto will use ODK_PrepareCoreRenewalRequest, as described in the
+ * document "Widevine Core Message Serialization", to prepare the core
+ * message.
+ *
+ * If it returns an error, the error should be returned by OEMCrypto to the
+ * CDM layer. If it returns OEMCrypto_SUCCESS, then OEMCrypto computes the
+ * signature using the renewal mac key which was delivered in the license via
+ * LoadLicense.
+ *
+ * If nonce_values.api_level is 16, then OEMCrypto shall compute the
+ * signature of the entire message using the session's client renewal mac
+ * key. The entire message is the buffer starting at message with length
+ * message_length.
+ *
+ * If nonce_values.api_major_version is 15, then OEMCrypto shall compute the
+ * signature of the message body using the session's client renewal mac key.
+ * The message body is the buffer starting at message+core_message_size with
+ * length message_length - core_message_size. If the session has not had a
+ * license loaded, it will use the usage entries client mac key to sign the
+ * message body.
+ *
+ * This function generates a HMAC-SHA256 signature using the mac_key[client]
+ * for license request signing under the license server protocol for CENC.
+ *
+ * The key used for signing should be the mac_key[client] that was generated
+ * for this session or loaded for this session by
+ * OEMCrypto_LoadLicense() or OEMCrypto_LoadUsageEntry().
+ *
+ * Refer to the Signing Messages Sent to a Server section above for more
+ * details.
+ *
+ * If a usage entry has been loaded, but keys have not been loaded through
+ * OEMCrypto_LoadLicense(), then the derived mac keys and the keys in the usage
+ * entry may be different. In this case, the mac keys specified in the usage
+ * entry should be used.
+ *
+ * NOTE: if signature pointer is null and/or input signature_length is zero,
+ * this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
+ * signature_length to the size needed to receive the output signature.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in,out] message: Pointer to memory for the entire message. Modified by
+ * OEMCrypto via the ODK library.
+ * @param[in] message_length: length of the entire message buffer.
+ * @param[in,out] core_message_size: length of the core message at the beginning
+ * of the message. (in) size of buffer reserved for the core message, in
+ * bytes. (out) actual length of the core message, in bytes.
+ * @param[out] signature: pointer to memory to receive the computed signature.
+ * @param[in,out] signature_length: (in) length of the signature buffer, in
+ * bytes. (out) actual length of the signature, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if signature buffer is not large enough
+ * to hold the signature.
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_size, uint8_t* signature, size_t* signature_length);
+
+/**
+ * Install a set of keys for performing decryption in the current session.
+ *
+ * First, OEMCrypto shall verify the signature of the message using
+ * HMAC-SHA256 with the derived mac_key[server]. The signature verification
+ * shall use a constant-time algorithm (a signature mismatch will always take
+ * the same time as a successful comparison). The signature is over the
+ * entire message buffer starting at message with length message_length. If
+ * the signature verification fails, ignore all other arguments and return
+ * OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session
+ * context.
+ *
+ * NOTE: The calling software must have previously established the mac_keys
+ * and encrypt_key with a call to OEMCrypto_DeriveKeysFromSessionKey().
+ *
+ * Refer to the Verification of Messages from a Server section above for more
+ * details.
+ *
+ * The function ODK_ParseLicense is called to parse the message. If it
+ * returns an error, OEMCrypto shall return that error to the CDM layer. The
+ * function ODK_ParseLicense is described in the document "Widevine Core
+ * Message Serialization".
+ *
+ * Below, all fields are found in the struct ODK_ParsedLicense parsed_license
+ * returned by ODK_ParseLicense.
+ *
+ * The keys will be decrypted using the current encrypt_key (AES-128-CBC) and
+ * the IV given in the KeyObject. If the API version of the license is less
+ * than 17, each key control block will be decrypted using the first 128 bits
+ * of the corresponding content key (AES-128-CBC) and the IV given in the
+ * KeyObject. In v17 licenses, the key control block is not decrypted.
+ *
+ * If its length is not zero, enc_mac_keys will be used to create new
+ * mac_keys. After all keys have been decrypted and validated, the new
+ * mac_keys are decrypted with the current encrypt_key and the offered IV.
+ * The new mac_keys replaces the current mac_keys for future signing renewal
+ * requests and loading renewal responses. The first 256 bits of the mac_keys
+ * become the mac_key[server] and the following 256 bits of the mac_keys
+ * become the mac_key[client]. If enc_mac_keys is null, then there will not
+ * be a call to OEMCrypto_LoadRenewal() for this session and the current
+ * mac_keys may be deleted.
+ *
+ * If the field license_type is OEMCrypto_ContentLicense, then the fields
+ * key_id and key_data in an OEMCrypto_KeyObject are loaded in to the
+ * content_key_id and content_key_data fields of the key table entry. In this
+ * case, entitlement key ids and entitlement key data is left blank.
+ *
+ * If the field license_type is OEMCrypto_EntitlementLicense, then the
+ * fields key_id and key_data in an OEMCrypto_KeyObject are loaded in to the
+ * entitlement_key_id and entitlement_key_data fields of the key table entry.
+ * In this case, content key ids and content key data will be loaded later
+ * with a call to OEMCrypto_LoadEntitledContentKeys().
+ *
+ * OEMCrypto may assume that the key_id_length is at most 16. However,
+ * OEMCrypto shall correctly handle key id lengths from 1 to 16 bytes.
+ *
+ * OEMCrypto shall handle multiple keys, as described in the document
+ * [Resource Rating Tiers](/widevine/drm/feature/resource-rating).
+ *
+ * After a call to OEMCrypto_LoadLicense(), oemcrypto should clear the
+ * encrypt_key for the session.
+ *
+ * @verification
+ * The following checks should be performed. If any check fails, an error is
+ * returned, and none of the keys are loaded.
+ * 13. The signature of the message shall be computed, and the API shall
+ * verify the computed signature matches the signature passed in. If
+ * not, return OEMCrypto_ERROR_SIGNATURE_FAILURE. The signature
+ * verification shall use a constant-time algorithm (a signature
+ * mismatch will always take the same time as a successful comparison).
+ * 14. If there already is a license loaded into this session, return
+ * OEMCrypto_ERROR_LICENSE_RELOAD.
+ * 15. The enc_mac_keys substring must either have zero length, or satisfy
+ * the range check. I.e. (offset < message_length) && (offset + length
+ * <= message_length) && (offset <= offset + length), and offset + length
+ * does not cause an integer overflow. If it does not have zero length,
+ * then enc_mac_keys_iv must not have zero length, and must also satisfy
+ * the range check. If not, return OEMCrypto_ERROR_INVALID_CONTEXT. If
+ * the length is zero, then OEMCrypto may assume that the offset is also
+ * zero.
+ * 16. The API shall verify that each substring in each KeyObject points to
+ * a location in the message. I.e. (offset < message_length) &&
+ * (offset + length <= message_length) && (offset <= offset + length),
+ * and offset + length does not cause an integer overflow, for each of
+ * key_id, key_data_iv, key_data, key_control_iv, key_control. If not,
+ * return OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 17. Each key's control block, after decryption, shall have a valid
+ * verification field. If not, return OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 18. If any key control block has the Nonce_Enabled bit set, that key's
+ * Nonce field shall match a nonce in the cache. If not, return
+ * OEMCrypto_ERROR_INVALID_NONCE. If there is a match, remove that
+ * nonce from the cache. Note that all the key control blocks in a
+ * particular call shall have the same nonce value.
+ * 19. If any key control block has the Require_AntiRollback_Hardware bit
+ * set, and the device does not protect the usage table from rollback,
+ * then do not load the keys and return OEMCrypto_ERROR_UNKNOWN_FAILURE.
+ * 20. If the key control block has a nonzero Replay_Control, then the
+ * verification described below is also performed.
+ * 21. If the key control block has the bit SRMVersionRequired is set, then
+ * the verification described below is also performed. If the SRM
+ * requirement is not met, then the key control block's HDCP_Version
+ * will be changed to 0xF - local display only.
+ * 22. If key_array_length == 0, then return
+ * OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 23. If this session is associated with a usage table entry, and that
+ * entry is marked as "inactive" (either kInactiveUsed or
+ * kInactiveUnused), then the keys are not loaded, and the error
+ * OEMCrypto_ERROR_LICENSE_INACTIVE is returned.
+ * 24. The data in enc_mac_keys_iv is not identical to the 16 bytes before
+ * enc_mac_keys. If it is, return OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 25. IF ODK_ParseLicense returns ODK_TIMER_EXPIRED, return
+ * OEMCrypto_ERROR_KEY_EXPIRED. If ODK_ParseLicense returns ODK_SET_TIMER
+ * or ODK_DISABLE_TIMER, the playback timer has started and OEMCrypto
+ * should treat this as if a Decrypt call has been made.
+ *
+ * Usage Table and Provider Session Token (pst)
+ * The function ODK_ParseLicense takes several parameters that may need more
+ * explanation.
+ * The parameter usage_entry_present shall be set to true if a usage entry
+ * was created or loaded for this session. This parameter is used by
+ * ODK_ParseLicense for usage entry verification.
+ * The parameter initial_license_load shall be false if the usage entry was
+ * loaded. If there is no usage entry or if the usage entry was created with
+ * OEMCrypto_CreateNewUsageEntry(), then initial_license_load shall be true.
+ * If a usage entry is present, then it shall be verified after the call to
+ * ODK_ParseLicense.
+ * If initial_license_load is true:
+ * 1. OEMCrypto shall copy the PST from the parsed license to the usage
+ * entry.
+ * 2. OEMCrypto shall verify that the server and client mac keys were
+ * updated by the license. The server and client mac keys shall be
+ * copied to the usage entry.
+ * If initial_license_load is false:
+ * 1. OEMCrypto shall verify the PST from the parsed license matches that
+ * in the usage entry. If not, then an error OEMCrypto_ERROR_WRONG_PST
+ * is returned.
+ * 2. OEMCrypto shall verify that the server and client mac keys were
+ * updated by the license. OEMCrypto shall verify that the server and
+ * client mac keys match those in the usage entry. If not the error
+ * OEMCrypto_ERROR_WRONG_KEYS is returned.
+ * If a key control block has a nonzero value for Replay_Control, then all
+ * keys in this license will have the same value for Replay_Control. In this
+ * case, the following additional checks are performed.
+ * - The substring pst must have nonzero length and must satisfy the range
+ * check described above. If not, return
+ * OEMCrypto_ERROR_INVALID_CONTEXT.
+ * - The session must be associated with a usage table entry, either
+ * created via OEMCrypto_CreateNewUsageEntry() or loaded via
+ * OEMCrypto_LoadUsageEntry().
+ * - If Replay_Control is 1 = Nonce_Required, then OEMCrypto will perform a
+ * nonce check as described above. OEMCrypto will verify that the
+ * usage entry is newly created with OEMCrypto_CreateNewUsageEntry(). If
+ * an existing entry was reloaded, an error
+ * OEMCrypto_ERROR_INVALID_CONTEXT is returned and no keys are loaded.
+ * OEMCrypto will then copy the pst and the mac keys to the usage entry,
+ * and set the status to Unused. The license received time of the entry
+ * will be updated to the current time, and the status will be set to
+ * Unused. This Replay_Control prevents the license from being loaded
+ * more than once, and will be used for online streaming.
+ * - If Replay_Control is 2 = "Require existing Session Usage table entry
+ * or Nonce", then OEMCrypto will behave slightly differently on the
+ * first call to LoadLicense for this license.
+ * * If the usage entry was created with OEMCrypto_CreateNewUsageEntry()
+ * for this session, then OEMCrypto will verify the nonce for each
+ * key. OEMCrypto will copy the pst and mac keys to the usage
+ * entry. The license received time of the entry will be updated
+ * to the current time, and the status will be set to Unused.
+ * * If the usage entry was loaded with OEMCrypto_LoadUsageEntry() for
+ * this session, then OEMCrypto will NOT verify the nonce for each
+ * key. Instead, it will verify that the pst passed in matches
+ * that in the entry. Also, the entry's mac keys will be verified
+ * against the current session's mac keys. This allows an offline
+ * license to be reloaded but maintain continuity of the playback
+ * times from one session to the next.
+ * * If the nonce is not valid and a usage entry was not loaded, the
+ * return error is OEMCrypto_ERROR_INVALID_NONCE.
+ * * If the loaded usage entry has a pst that does not match,
+ * OEMCrypto returns the error OEMCrypto_ERROR_WRONG_PST.
+ * * If the loaded usage entry has mac keys that do not match the
+ * license, OEMCrypto returns the error OEMCrypto_ERROR_WRONG_KEYS.
+ * Note: If LoadLicense updates the mac keys, then the new updated mac keys will
+ * be used with the Usage Entry -- i.e. the new keys are stored in the
+ * usage table when creating a new entry, or the new keys are verified
+ * against those in the usage table if there is an existing entry. If
+ * LoadLicense does not update the mac keys, the existing session mac keys are
+ * used.
+ * Sessions that are associated with an entry will need to be able to update
+ * and verify the status of the entry, and the time stamps in the entry.
+ * Devices that do not support the Usage Table will return
+ * OEMCrypto_ERROR_INVALID_CONTEXT if the Replay_Control is nonzero.
+ * SRM Restriction Data
+ * If any key control block has the flag SRMVersionRequired set, then the
+ * following verification is also performed.
+ * 4. The substring srm_restriction_data must have nonzero length and must
+ * satisfy the range check described above. If not, return
+ * OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 5. The first 8 bytes of srm_restriction_data must match the string
+ * "HDCPDATA". If not, return OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 6. The next 4 bytes of srm_restriction_data will be converted from
+ * network byte order. If the current SRM installed on the device has a
+ * version number less than this, then the SRM requirement is not met.
+ * If the device does not support SRM files, or OEMCrypto cannot
+ * determine the current SRM version number, then the SRM requirement is
+ * not met.
+ * Note: if the current SRM version requirement is not met, LoadLicense will
+ * still succeed and the keys will be loaded. However, those keys with the
+ * SRMVersionRequired bit set will have their HDCP_Version increased to 0xF -
+ * local display only. Any future call to OEMCrypto_GetKeyHandle() for these
+ * keys while there is an external display will return
+ * OEMCrypto_ERROR_INSUFFICIENT_HDCP at that time.
+ *
+ * @param[in] session: crypto session identifier.
+ * @param[in] message: pointer to memory containing data.
+ * @param[in] message_length: length of the message, in bytes.
+ * @param[in] core_message_length: length of the core submessage, in bytes.
+ * @param[in] signature: pointer to memory containing the signature.
+ * @param[in] signature_length: length of the signature, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
+ * @retval OEMCrypto_ERROR_INVALID_NONCE
+ * @retval OEMCrypto_ERROR_TOO_MANY_KEYS
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_LICENSE_RELOAD
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_LoadLicense(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ size_t core_message_length,
+ const uint8_t* signature,
+ size_t signature_length);
+
+/**
+ * Updates the clock values and resets the renewal timer for the current
+ * session.
+ *
+ * OEMCrypto shall verify the signature of the entire message using the
+ * session's renewal mac key for the server. The entire message is the buffer
+ * starting at message with length message_length. If the signature does not
+ * match, OEMCrypto returns OEMCrypto_ERROR_SIGNATURE_FAILURE.
+ *
+ * OEMCrypto shall verify that nonce_values.api_major_version is 16. If not,
+ * return the error OEMCrypto_ERROR_INVALID_CONTEXT.
+ *
+ * If the signature passes, OEMCrypto shall use the function
+ * ODK_ParseRenewal, as described in the document "Widevine Core Message
+ * Serialization" to parse and verify the message. If ODK_ParseRenewal
+ * returns an error OEMCrypto returns the error to the CDM layer.
+ *
+ * The function ODK_ParseRenewal updates the clock values for the session,
+ * and may return ODK_SET_TIMER, ODK_DISABLE_TIMER or ODK_TIMER_EXPIRED on
+ * success. These values shall be handled by OEMCrypto, as discussed in the
+ * document "License Duration and Renewal".
+ *
+ * NOTE: OEMCrypto_LoadLicense() must be called first to load the keys into
+ * the session.
+ *
+ * @verification
+ * The signature of the message shall be computed using mac_key[server], and
+ * the API shall verify the computed signature matches the signature passed
+ * in. If not, return OEMCrypto_ERROR_SIGNATURE_FAILURE. The signature
+ * verification shall use a constant-time algorithm (a signature mismatch
+ * will always take the same time as a successful comparison).
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] message: pointer to memory containing message to be verified.
+ * @param[in] message_length: length of the message, in bytes.
+ * @param[in] core_message_length: length of the core submessage, in bytes.
+ * @param[in] signature: pointer to memory containing the signature.
+ * @param[in] signature_length: length of the signature, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
+ * @retval OEMCrypto_ERROR_INVALID_NONCE
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval ODK_STALE_RENEWAL
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 12.
+ */
+OEMCryptoResult OEMCrypto_LoadRenewal(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ size_t core_message_length,
+ const uint8_t* signature,
+ size_t signature_length);
+
+/**
+ * Returns the decrypted key control block for the given content_key_id. This
+ * function is for application developers to debug license server and key
+ * timelines. It only returns a key control block if LoadLicense was successful,
+ * otherwise it returns OEMCrypto_ERROR_NO_CONTENT_KEY. The developer of the
+ * OEMCrypto library must be careful that the keys themselves are not
+ * accidentally revealed.
+ *
+ * Note: returns control block in original, network byte order. If OEMCrypto
+ * converts fields to host byte order internally for storage, it should
+ * convert them back. Since OEMCrypto might not store the nonce or validation
+ * fields, values of 0 may be used instead.
+ *
+ * @verification
+ * The following checks should be performed.
+ * 1. If key_id is null, return OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 2. If key_control_block_length is null, return
+ * OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 3. If *key_control_block_length is less than the length of a key control
+ * block, set it to the correct value, and return
+ * OEMCrypto_ERROR_SHORT_BUFFER.
+ * 4. If key_control_block is null, return OEMCrypto_ERROR_INVALID_CONTEXT.
+ * 5. If the specified key has not been loaded, return
+ * OEMCrypto_ERROR_NO_CONTENT_KEY.
+ *
+ * @param[in] session: handle for the crypto or entitled key session to be used.
+ * @param[in] content_key_id: The unique id of the key of interest.
+ * @param[in] content_key_id_length: The length of key_id, in bytes. From 1 to
+ * 16, inclusive.
+ * @param[out] key_control_block: A caller-owned buffer.
+ * @param[in,out] key_control_block_length. The length of key_control_block
+ * buffer.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is changed in API version 17.
+ */
+OEMCryptoResult OEMCrypto_QueryKeyControl(OEMCrypto_SESSION session,
+ const uint8_t* content_key_id,
+ size_t content_key_id_length,
+ uint8_t* key_control_block,
+ size_t* key_control_block_length);
+
+/// @}
+
+/// @addtogroup entitled
+/// @{
+
+/**
+ * This method creates an entitled key session.
+ * OEMCrypto is required to support at least one entitled key session per
+ * license. For CAS support, we also require that OEMCrypto support at least
+ * six entitled key sessions per license.
+ *
+ * @param[in] oec_session: handle for the OEMCrypto session to be associated
+ * with the created entitled key session.
+ * @param[out] key_session: id of the created entitled key session.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_TOO_MANY_SESSIONS
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this oec_session. It will not be called simultaneously with
+ * initialization or usage table functions. It is as if the CDM holds a write
+ * lock for this session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_CreateEntitledKeySession(
+ OEMCrypto_SESSION oec_session, OEMCrypto_SESSION* key_session);
+
+/**
+ * This method which removes an entitled key session.
+ *
+ * @param[in] key_session: id of the entitled key session to be removed.
+ *
+ * Returns:
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_RemoveEntitledKeySession(
+ OEMCrypto_SESSION key_session);
+
+/**
+ * Load content keys into an entitled session which is associated with an
+ * entitlement sessions. This function will only be called for an entitled
+ * session after a call to OEMCrypto_LoadLicense() has been called on the
+ * associated entitlement session. This function may be called multiple times
+ * for the same session.
+ *
+ * If the session is not an entitled session, return
+ * OEMCrypto_ERROR_INVALID_CONTEXT and perform no work.
+ *
+ * For each key object in key_array, OEMCrypto shall look up the entry in the
+ * key table for the entitlement session with the corresponding
+ * entitlement_key_id.
+ *
+ * 1. If no entry is found, return OEMCrypto_KEY_NOT_ENTITLED.
+ * 2. If the entry already has a content_key_id and content_key_data, that
+ * id and data are erased.
+ * 3. The content_key_id from the key_array is copied to the entry's
+ * content_key_id.
+ * 4. The content_key_data decrypted using the entitlement_key_data as a
+ * key for AES-256-CBC with an IV of content_key_data_iv. Notice that
+ * the entitlement key will be an AES 256 bit key. The clear content key
+ * data will be stored in the entry's content_key_data.
+ * Entries in the key table that do not correspond to anything in the
+ * key_array are not modified or removed.
+ *
+ * For devices that use a hardware key ladder, it may be more convenient to
+ * store the encrypted content key data in the key table, and decrypt it when
+ * the function OEMCrypto_GetKeyHandle() is called.
+ *
+ * @param[in] session: handle for the entitled key session to be used.
+ * @param[in] message: pointer to memory containing message to be verified.
+ * @param[in] message_length: length of the message, in bytes.
+ * @param[in] key_array_length: number of keys present.
+ * @param[in] key_array: set of key updates.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_KEY_NOT_ENTITLED
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session, or its entitlement session. It will not be called
+ * simultaneously with initialization or usage table functions. It is as if
+ * the CDM holds a write lock for this session, and a read lock on the
+ * OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 17.
+ */
+OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ size_t key_array_length,
+ const OEMCrypto_EntitledContentKeyObject* key_array);
+
+/**
+ * This method associates an existing entitled key session to the specified
+ * OEMCrypto session.
+ *
+ * @param[in] key_session: id of the entitled key session.
+ * @param[in] oec_session: handle for the OEMCrypto session to be associated
+ * with the entitled key session.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ *
+ * @threading
+ * This is a "Session Initialization Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock
+ * on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_ReassociateEntitledKeySession(
+ OEMCrypto_SESSION key_session, OEMCrypto_SESSION oec_session);
+
+/**
+ * The OEMCrypto_LoadCasECMKeys method is added to load content keys into an
+ * entitled key session, which already has entitlement keys loaded. Used only by
+ * CAS.
+ *
+ * This function will only be called for a session after a call to
+ * OEMCrypto_LoadLicense with the license_type equal to
+ * OEMCrypto_EntitlementLicense, and a call to
+ * OEMCrypto_CreateEntitledKeySession initializing the entitled key session.
+ * This function may be called multiple times for the same session.
+ *
+ * For each key object, odd and even, OEMCrypto shall look up the entry in the
+ * key table with the corresponding entitlement_key_id. Before the
+ * entitlement_key is used:
+ * 1) If no entry is found, return OEMCrypto_KEY_NOT_ENTITLED.
+ * 2) Check the entitlement key’s key control block use. If failed, return
+ * corresponding error code such as OEMCrypto_ERROR_ANALOG_OUTPUT,
+ * OEMCrypto_ERROR_INSUFFICIENT_HDCP.
+ * 3) If the entitlement key’s control block has a nonzero Duration field,
+ * then the API shall verify that the duration is greater than the
+ * session’s elapsed time clock before the key is used. OEMCrypto will
+ * return OEMCrypto_ERROR_KEY_EXPIRED.
+ * 4) The content_key_data decrypted using the entitlement_key_data as a key
+ * for AES-256-CBC with an IV of content_key_data_iv. Wrapped content is
+ * padded using PKCS#7 padding. Notice that the entitlement key will be an
+ * AES 256 bit key. The clear content key data will be stored in the
+ * entry’s content_key_data.
+ * 5) The decrypted content key data may be set in a hardware KeySlot,
+ * together with content iv and cipher mode information, which can be used
+ * by the Descrambler in TunerHal. The entitled key session ID may be used
+ * as the key token to uniquely identify the content key in KeySlot.
+ *
+ * @param[in] session: handle for the entitled key session to be used.
+ * @param[in] message: pointer to memory containing message to be verified.
+ * @param[in] message_length: length of the message, in bytes.
+ * @param[in] even_key: key update for the even ecm key. May be null if the key
+ * does not change.
+ * @param[in] odd_key: key update for the odd ecm key. May be null if the key
+ * does not change.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_KEY_NOT_ENTITLED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ * @retval OEMCrypto_ERROR_ANALOG_OUTPUT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_HDCP
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_LoadCasECMKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const OEMCrypto_EntitledContentKeyObject* even_key,
+ const OEMCrypto_EntitledContentKeyObject* odd_key);
+
+/**
+ * Retrieves the key token associated with the input entitled key session. This
+ * method is currently used only by CAS, where key token is a means to share
+ * vendor specific crypto info with other frameworks (e.g. Descrambler in
+ * Android TunerHAL) that are also under control of the vendor.
+ *
+ * @param[in] key_session: handle for the entitled key session to be used.
+ * @param[out] key_token: where the key token is stored.
+ * @param[in,out] key_token_length: length of the key token, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS on success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if buffer_length is too small.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock on
+ * the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_GetOEMKeyToken(OEMCrypto_SESSION key_session,
+ uint8_t* key_token,
+ size_t* key_token_length);
+
+/// @}
+
+/// @addtogroup decryption
+/// @{
+
+/**
+ * Select a content key and install it in the hardware key ladder for
+ * subsequent decryption operations. (e.g. OEMCrypto_DecryptCENC(), generic
+ * crypto functions) The specified key must have been previously imported via
+ * OEMCrypto_LoadLicense() or OEMCrypto_LoadEntitledContentKeys(). Write a
+ * handle that can be used to refer to the installed key into the buffer pointed
+ * to by the key_handle parameter and set key_handle_length to the size of the
+ * data written to key_handle.
+ *
+ * If key_handle is NULL or key_handle_length is too small to hold the handle,
+ * write the number of bytes needed to hold a key handle to key_handle_length
+ * and return OEMCrypto_ERROR_SHORT_BUFFER. Do not install the key in this case.
+ *
+ * If the session has an entry in the Usage Table and the status of the entry is
+ * "unused", then change the status to "active" and set the
+ * time_of_first_decrypt.
+ *
+ * A key control block is associated with the key and the session, and is
+ * used to configure the session context. The Key Control data is documented
+ * in "Key Control Block Definition".
+ *
+ * Step 1: Lookup the content key data via the offered key_id. The key data
+ * includes the key value, and the key control block.
+ *
+ * Step 2: Latch the content key into the hardware key ladder. Set permission
+ * flags based on the key's control block.
+ *
+ * Step 3: use the latched content key to decrypt (AES-128-CTR or
+ * AES-128-CBC) buffers passed in via OEMCrypto_DecryptCENC(). If the key is
+ * 256 bits it will be used for OEMCrypto_Generic_Sign() or
+ * OEMCrypto_Generic_Verify() as specified in the key control block. If the key
+ * will be used for OEMCrypto_Generic_Encrypt() or OEMCrypto_Generic_Decrypt()
+ * then the cipher mode will always be OEMCrypto_CipherMode_CBCS.
+ *
+ * #### Bypass Decrypt
+ *
+ * Platforms that wish to support Bypass Decrypt should latch the key into
+ * secure crypto hardware such that it can be fed by the chosen bypass method.
+ * For more information on Bypass Decrypt, see the
+ * [Bypass Decrypt](../../bypass) documentation.
+ *
+ * If the device is bypassing, it must update the ODK clock values in this
+ * function call. If this is the first use of a key for this session, then
+ * OEMCrypto shall call ODK_AttemptFirstPlayback to update the session's clock
+ * values and verify playback is allowed. If this is not the first use of a key
+ * for this session, then OEMCrypto shall call ODK_UpdateLastPlaybackTime. See
+ * [ODK Clocks and Timers](../../odk-timers) for handling the return value of
+ * these ODK functions. The hardware that the key is latched into must be able
+ * to enforce that the key expires and becomes unusable after the amount of
+ * time returned by ODK in the timer_value field.
+ *
+ * The format of the key handle is opaque to Widevine and platform-specific. It
+ * should contain whatever information the platform will need to find the key in
+ * the hardware on the bypass decryption path, as well as in
+ * OEMCrypto_DecryptCENC() and the generic crypto functions. A key slot number
+ * is generally not sufficient, as this could lead to the wrong key being used
+ * if that slot later has a different key loaded into it.
+ *
+ * The key handle must not contain the actual cryptographic key.
+ *
+ * #### Non-Bypass Decrypt
+ *
+ * For platforms that do not need to support Bypass Decrypt, a mode compatible
+ * with previous versions of OEMCrypto is available. These devices may latch the
+ * key to the session and continue to use this key for this session until
+ * OEMCrypto_GetKeyHandle() is called again, or until OEMCrypto_CloseSession()
+ * is called.
+ *
+ * The "key handle" in this mode is the session ID. Platforms should request a
+ * 4-byte key handle buffer and copy the session ID into it.
+ *
+ * @verification
+ * 1. If the key id is not found in the keytable for this session, then the
+ * key state is not changed and OEMCrypto shall return
+ * OEMCrypto_ERROR_NO_CONTENT_KEY.
+ * 2. If the key control block has the bit Disable_Analog_Output set, then
+ * the device should disable analog video output. If the device has
+ * analog video output that cannot be disabled, then the key is not
+ * selected, and OEMCrypto_ERROR_ANALOG_OUTPUT is returned. This step is
+ * optional -- OEMCrypto_GetKeyHandle() may return OEMCrypto_SUCCESS and
+ * delay the error until a call to OEMCrypto_DecryptCENC().
+ * 3. If the key control block has HDCP required, and the device cannot
+ * enforce HDCP, then the key is not selected, and
+ * OEMCrypto_ERROR_INSUFFICIENT_HDCP is returned. This step is optional
+ * -- OEMCrypto_GetKeyHandle() may return OEMCrypto_SUCCESS and delay the
+ * error until a call to OEMCrypto_DecryptCENC().
+ * 4. If the key control block has a nonzero value for HDCP_Version, and
+ * the device cannot enforce at least that version of HDCP, then the key
+ * is not selected, and OEMCrypto_ERROR_INSUFFICIENT_HDCP is returned.
+ *
+ * @param[in] session: handle for the crypto or entitled key session to be used.
+ * @param[in] content_key_id: pointer to the content Key ID.
+ * @param[in] content_key_id_length: length of the content Key ID, in bytes.
+ * From 1 to 16, inclusive.
+ * @param[in] cipher_mode: whether the key should be prepared for CTR mode or
+ * CBC mode when used in later calls to DecryptCENC. This should be ignored
+ * when the key is used for Generic Crypto calls.
+ * @param[out] key_handle: pointer to a buffer in which the key handle should be
+ * stored. May be NULL on the first call in order to find required buffer
+ * size.
+ * @param[in,out] key_handle_length: (in) length of the key_handle buffer, in
+ * bytes. (out) actual length of the key handle written to the key_handle
+ * buffer, in bytes. May not be NULL.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the buffer is NULL or too small
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED if the session's timer has expired
+ * @retval OEMCrypto_ERROR_INVALID_SESSION crypto session ID invalid or not open
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY failed to decrypt device key
+ * @retval OEMCrypto_ERROR_NO_CONTENT_KEY failed to decrypt content key
+ * @retval OEMCrypto_ERROR_CONTROL_INVALID invalid or unsupported control input
+ * @retval OEMCrypto_ERROR_KEYBOX_INVALID cannot decrypt and read from Keybox
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_ANALOG_OUTPUT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_HDCP
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 18.
+ */
+OEMCryptoResult OEMCrypto_GetKeyHandle(OEMCrypto_SESSION session,
+ const uint8_t* content_key_id,
+ size_t content_key_id_length,
+ OEMCryptoCipherMode cipher_mode,
+ uint8_t* key_handle,
+ size_t* key_handle_length);
+
+/**
+ * Decrypts or copies a series of input payloads into output buffers using
+ * the installed key indicated by the key handle parameter. The input payload
+ * is delivered in the form of samples. The samples are subdivided into
+ * subsamples. "Samples" and "subsamples" are defined as in the ISO Common
+ * Encryption standard (ISO/IEC 23001-7:2016). The samples parameter contains
+ * a list of samples, each of which has its own input and output buffers.
+ * Each sample contains a buffers field that contains the input and output
+ * buffers in its input_data and output fields, respectively.
+ *
+ * Each sample contains an array of subsample descriptions in its subsamples
+ * field. Each subsample is defined as a number of clear bytes followed by a
+ * number of encrypted bytes. Subsamples are consecutive inside the sample;
+ * the clear bytes of the second subsample begin immediately after the
+ * encrypted bytes of the first subsample. This follows the definition in the
+ * ISO-CENC standard.
+ *
+ * Decryption mode is AES-128-CTR or AES-128-CBC depending on the value of
+ * cipher_mode previously passed in to OEMCrypto_GetKeyHandle(). For the
+ * encrypted portion of subsamples, the content key associated with the handle
+ * is latched in the active hardware key ladder and is used for the decryption
+ * operation. For the clear portion of subsamples, the data is simply copied.
+ *
+ * After decryption, all the input_data bytes are copied to the location
+ * described by the output field. The output field is an
+ * OEMCrypto_DestBufferDesc, which could be one of:
+ *
+ * 1. The structure OEMCrypto_DestBufferDesc contains a pointer to a clear
+ * text buffer. The OEMCrypto library shall verify that key control
+ * allows data to be returned in clear text. If it is not authorized,
+ * this method should return an error.
+ * 2. The structure OEMCrypto_DestBufferDesc contains a handle to a secure
+ * buffer.
+ * 3. The structure OEMCrypto_DestBufferDesc indicates that the data should
+ * be sent directly to the decoder and renderer.
+ *
+ * Depending on your platform's needs, you may not need to support all three
+ * of these options.
+ *
+ * SINGLE-SAMPLE DECRYPTION AND SINGLE-SUBSAMPLE DECRYPTION:
+ *
+ * If the OEMCrypto implementation is not able to handle the amount of
+ * samples and subsamples passed into it, it should return
+ * OEMCrypto_ERROR_BUFFER_TOO_LARGE, in which case the CDM can respond by
+ * breaking the samples up into smaller pieces and trying to decrypt each of
+ * them individually. It is possible that the CDM will break the samples
+ * array up into pieces that are still too large, in which case OEMCrypto may
+ * return OEMCrypto_ERROR_BUFFER_TOO_LARGE again.
+ *
+ * If the OEMCrypto implementation cannot handle multiple samples at once, it
+ * may return OEMCrypto_ERROR_BUFFER_TOO_LARGE any time it receives more than
+ * one sample in a single call to OEMCrypto_DecryptCENC().
+ *
+ * Similarly, if the OEMCrypto implementation cannot handle multiple
+ * subsamples at once, it may return OEMCrypto_ERROR_BUFFER_TOO_LARGE any
+ * time it receives more than one subsample in a single call to
+ * OEMCrypto_DecryptCENC().
+ *
+ * The exact way that the CDM code breaks up the samples array is not
+ * guaranteed by this specification. The CDM may break down the array of
+ * samples into many arrays each containing one sample. The CDM may break
+ * down samples into subsamples and pass individual subsamples into
+ * OEMCrypto, just like in OEMCrypto v15. The CDM may break down individual
+ * subsamples into smaller subsamples, just like in OEMCrypto v15.
+ *
+ * If OEMCrypto requests that the CDM break samples into subsamples, the
+ * "samples" passed into OEMCrypto_DecryptCENC() will no longer be full
+ * samples. When a full sample is passed into OEMCrypto_DecryptCENC(), the
+ * first subsample in the subsample array will have the
+ * OEMCrypto_FirstSubsample flag set in its subsample_flags field and the
+ * last subsample array will have the OEMCrypto_LastSubsample flag set in its
+ * subsample_flags field. If this is not the case, OEMCrypto will need to
+ * accumulate more subsamples from successive calls to OEMCrypto_DecryptCENC
+ * to receive the full sample.
+ *
+ * The first subsample in the sample will always have OEMCrypto_FirstSubsample
+ * set and the last subsample will always have the OEMCrypto_LastSubsample flag
+ * set, even if those subsamples are passed in separate calls to
+ * OEMCrypto_DecryptCENC(). This is the same as in OEMCrypto v15. The decrypted
+ * data will not be used until after the subsample with the flag
+ * OEMCrypto_LastSubsample has been sent to OEMCrypto. This can be relied on by
+ * OEMCrypto for optimization by not doing decrypt until the last subsample has
+ * been received. However, a device that can do decrypt of more than one
+ * subsample at a time will always have better performance if it can receive
+ * those subsamples in one OEMCrypto_DecryptCENC() call rather than as
+ * individual subsamples.
+ *
+ * Although the exact way that the CDM code breaks up the samples array when
+ * it receives OEMCrypto_ERROR_BUFFER_TOO_LARGE is not guaranteed by this
+ * specification, here is a sample way it might work:
+ *
+ * 1. It tries to pass the array of samples to OEMCrypto_DecryptCENC().
+ * 2. If OEMCrypto returns OEMCrypto_ERROR_BUFFER_TOO_LARGE, it tries to
+ * pass each sample individually into OEMCrypto_DecryptCENC().
+ * 3. If OEMCrypto returns OEMCrypto_ERROR_BUFFER_TOO_LARGE, it tries to
+ * pass the clear and encrypted parts of each subsample individually
+ * into OEMCrypto_DecryptCENC(). At this point, (and in the subsequent
+ * steps) it is replicating the behavior of OEMCrypto v15 and lower.
+ * 4. If OEMCrypto returns OEMCrypto_ERROR_BUFFER_TOO_LARGE, it breaks each
+ * piece of a subsample into smaller pieces, down to the minimum
+ * subsample size required by the device's resource rating tier. It
+ * passes these pieces into OEMCrypto_DecryptCENC().
+ * 5. If OEMCrypto returns OEMCrypto_ERROR_BUFFER_TOO_LARGE, the device has
+ * failed to meet its resource rating tier requirements. It returns an
+ * error.
+ * Because this process requires a lot of back-and-forth between the CDM and
+ * OEMCrypto, partners are strongly recommended to support decrypting full
+ * samples or even multiple samples in their OEMCrypto implementation.
+ *
+ * ISO-CENC SCHEMES:
+ *
+ * The ISO Common Encryption standard (ISO/IEC 23001-7:2016) defines four
+ * "schemes" that may be used to encrypt content: 'cenc', 'cens', 'cbc1', and
+ * 'cbcs'. Starting with v16, OEMCrypto only supports 'cenc' and 'cbcs'. The
+ * schemes 'cens' and 'cbc1' are not supported.
+ *
+ * The decryption mode, either OEMCrypto_CipherMode_CENC or
+ * OEMCrypto_CipherMode_CBCS, was already specified in the call to
+ * OEMCrypto_GetKeyHandle(). The encryption pattern is specified by the fields
+ * in the parameter pattern. A description of partial encryption patterns for
+ * 'cbcs' can be found in the ISO-CENC standard, section 10.4.
+ *
+ * 'cenc' SCHEME:
+ *
+ * The 'cenc' scheme is OEMCrypto_CipherMode_CENC without an encryption
+ * pattern. All the bytes in the encrypted portion of each subsample are
+ * encrypted. In the pattern parameter, both the encrypt and skip fields will
+ * be zero.
+ *
+ * The length of a crypto block in AES-128 is 16 bytes. In the 'cenc' scheme,
+ * if an encrypted subsample has a length that is not a multiple of 16 bytes,
+ * then all the bytes of the encrypted subsample must be decrypted, but the
+ * next encrypted subsample will begin by completing the incomplete crypto
+ * block from the previous encrypted subsample. The following diagram
+ * provides an example:
+ *
+ * 
+ *
+ * To help with this, the block_offset field of each subsample will contain
+ * the number of bytes the initial crypto block of that subsample should be
+ * offset by. In the example above, the block_offset for the first subsample
+ * would be 0 and the block_offset for the second subsample would be 12.
+ * 'cenc' is the only mode that allows for a nonzero block_offset. This field
+ * satisfies 0 <= block_offset < 16.
+ *
+ * 'cbcs' SCHEME:
+ *
+ * The 'cbcs' scheme is OEMCrypto_CipherMode_CBCS with an encryption pattern.
+ * Only some of the bytes in the encrypted portion of each subsample are
+ * encrypted. In the pattern parameter, the encrypt and skip fields will
+ * usually be non-zero. This mode allows devices to decrypt FMP4 HLS content,
+ * SAMPLE-AES HLS content, as well as content using the DASH 'cbcs' scheme.
+ *
+ * The skip field of OEMCrypto_CENCEncryptPatternDesc may also be zero. If
+ * the skip field is zero, then patterns are not in use and all crypto blocks
+ * in the encrypted part of the subsample are encrypted. It is not valid for
+ * the encrypt field to be zero.
+ *
+ * The length of a crypto block in AES-128 is 16 bytes. In the 'cbcs' scheme,
+ * if the encrypted part of a subsample has a length that is not a multiple
+ * of 16 bytes, then the final bytes that do not make up a full crypto block
+ * are clear and should never be decrypted. The following diagram provides an
+ * example:
+ *
+ * 
+ *
+ * Whether any given protected block is actually encrypted also depends on
+ * the pattern. But the bytes at the end that do not make up a full crypto
+ * block will never be encrypted, regardless of what the pattern is. Even if
+ * the pattern says to decrypt every protected block, these bytes are clear
+ * and should not be decrypted.
+ *
+ * Of course, if the encrypted subsample has a length that is a multiple of
+ * 16 bytes, all the bytes in it are protected, and they may need to be
+ * decrypted following the pattern. The following diagram provides an example:
+ *
+ * 
+ *
+ * INITIALIZATION VECTOR BETWEEN SUBSAMPLES:
+ *
+ * The IV is specified for the initial subsample in a sample in the iv field
+ * of the OEMCrypto_SampleDescription. OEMCrypto is responsible for correctly
+ * updating the IV for subsequent subsamples according to the ISO Common
+ * Encryption standard (ISO/IEC 23001-7:2016). Section 9.5.2.3 covers 'cenc'
+ * and section 9.5.2.5 covers 'cbcs'. A summary of the ISO-CENC behavior
+ * follows:
+ *
+ * For 'cenc', the IV at the end of each subsample carries forward to the
+ * next subsample and becomes the IV at the beginning of the next subsample.
+ * If the subsample ends on a crypto block boundary, then the IV should be
+ * incremented as normal at the end of the crypto block. If the subsample
+ * ends in the middle of a crypto block, the same IV should continue to be
+ * used until the crypto block is completed in the next subsample. Only
+ * increment the IV after the partial crypto block is completed.
+ *
+ * For 'cbcs', the IV is reset at the beginning of each subsample. Each
+ * subsample should start with the IV that was passed into
+ * OEMCrypto_DecryptCENC().
+ *
+ * To phrase it another way: In 'cenc', the encrypted portions of the
+ * subsamples can be concatenated to form one continuous ciphertext. In
+ * 'cbcs', each encrypted portion of a subsample is a separate ciphertext.
+ * Each separate ciphertext begins with the IV specified in the iv field of
+ * the OEMCrypto_SampleDescription.
+ *
+ * INITIALIZATION VECTOR WITHIN SUBSAMPLES:
+ *
+ * Once it has the IV for each subsample, OEMCrypto is responsible for
+ * correctly updating the IV for each crypto block of each encrypted
+ * subsample portion, as outlined in the ISO Common Encryption standard
+ * (ISO/IEC 23001-7:2016). Section 9.5.1 includes general information about
+ * IVs in subsample decryption. A summary of the ISO-CENC behavior follows:
+ *
+ * For 'cenc', the subsample's IV is the counter value to be used for the
+ * initial encrypted block of the subsample. The IV length is the AES block
+ * size. For subsequent encrypted AES blocks, OEMCrypto must calculate the IV
+ * by incrementing the lower 64 bits (byte 8-15) of the IV value used for the
+ * previous block. The counter rolls over to zero when it reaches its maximum
+ * value (0xFFFFFFFFFFFFFFFF). The upper 64 bits (byte 0-7) of the IV do not
+ * change.
+ *
+ * For 'cbcs', the subsample's IV is the initialization vector for the
+ * initial encrypted block of the subsample. Within each subsample, each
+ * crypto block is used as the IV for the next crypto block, as prescribed by
+ * AES-CBC.
+ *
+ * NOTES:
+ *
+ * If the destination buffer is secure, an offset may be specified.
+ * OEMCrypto_DecryptCENC() begins storing data buffers.output.secure.offset
+ * bytes after the beginning of the secure buffer.
+ *
+ * OEMCrypto cannot assume that the buffers of consecutive samples are
+ * consecutive in memory.
+ *
+ * A subsample may consist entirely of encrypted bytes or clear bytes. In
+ * this case, the clear or the encrypted part of the subsample will be zero,
+ * indicating that no bytes of that kind appear in the subsample.
+ *
+ * The ISO-CENC spec implicitly limits both the skip and encrypt values to be
+ * 4 bits, so they are at most 15.
+ *
+ * 
+ *
+ * If OEMCrypto assembles all of the encrypted subsample portions into a
+ * single buffer and then decrypts it in one pass, it can assume that the
+ * block offset is 0.
+ *
+ * 
+ *
+ * @verification
+ * The total size of all the subsamples cannot exceed the total size of the
+ * input buffer. OEMCrypto integrations should validate this and return
+ * OEMCrypto_ERROR_UNKNOWN_FAILURE if the subsamples are larger than the
+ * input buffer. No decryption should be performed in this case.
+ * If the subsamples all contain only clear bytes, then no further
+ * verification is performed.
+ * The following checks should be performed if any subsamples contain any
+ * encrypted bytes. If any check fails, an error is returned, and no
+ * decryption is performed.
+ * 1. If the current key's control block has the Data_Path_Type bit set,
+ * then the API shall verify that the output buffer is secure or direct.
+ * If not, return OEMCrypto_ERROR_DECRYPT_FAILED.
+ * 2. If the current key control block has the bit Disable_Analog_Output
+ * set, then the device should disable analog video output. If the
+ * device has analog video output that cannot be disabled, then
+ * OEMCrypto_ERROR_ANALOG_OUTPUT is returned. (See note on delayed
+ * error conditions below)
+ * 3. If the current key's control block has the HDCP bit set, then the API
+ * shall verify that the buffer will be displayed locally, or output
+ * externally using HDCP only. If not, return
+ * OEMCrypto_ERROR_INSUFFICIENT_HDCP. (See note on delayed error
+ * conditions below)
+ * 4. If the current key's control block has a nonzero value for
+ * HDCP_Version, then the current version of HDCP for the device and the
+ * display combined will be compared against the version specified in
+ * the control block. If the current version is not at least as high as
+ * that in the control block, and the device is not able to restrict
+ * displays with HDCP levels lower than what's in the control block,
+ * return OEMCrypto_ERROR_INSUFFICIENT_HDCP. If the device is able to
+ * restrict those displays, return
+ * OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION. (See note on delayed
+ * error conditions below)
+ * 5. If the current key has an entry in the Usage Table, and the status of
+ * that entry is either kInactiveUsed or kInactiveUnused, then return the
+ * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ * 6. If a Decrypt Hash has been initialized via OEMCrypto_SetDecryptHash(),
+ * and the current key's control block does not have the
+ * Allow_Hash_Verification bit set, then do not compute a hash and
+ * return OEMCrypto_ERROR_UNKNOWN_FAILURE.
+ *
+ * #### Delayed Error Conditions
+ *
+ * On some devices, the HDCP subsystem is not directly connected to the
+ * OEMCrypto TA. This means that returning the error
+ * OEMCrypto_ERROR_INSUFFICIENT_HDCP at the time of the decrypt call is a
+ * performance hit. However, some devices have the ability to tag output
+ * buffers with security requirements, such as the required HDCP level.
+ * For those devices, when a call to OEMCrypto_DecryptCENC() is made using a
+ * key that requires HDCP output, and if the HDCP level on the output does
+ * not meet the required level.
+ * - OEMCrypto may tag the output buffer as requiring HDCP at the required
+ * level and return OEMCrypto_SUCCESS.
+ * - Output shall not be sent to the display.
+ * - On the second or third call to OEMCrypto_DecryptCENC() with the same
+ * key, OEMCrypto shall return OEMCrypto_ERROR_INSUFFICIENT_HDCP.
+ * For those devices, when a call to OEMCrypto_DecryptCENC() is made using a
+ * key that requires HDCP output, and if the HDCP level on some of the
+ * displays does not meet the required level.
+ * - OEMCrypto may tag the output buffer as requiring HDCP at the required
+ * level and return OEMCrypto_SUCCESS.
+ * - Output shall only be sent to the display with sufficient output
+ * control, e.g. the local display.
+ * - On the second or third call to OEMCrypto_DecryptCENC() with the same
+ * key, OEMCrypto shall return OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION.
+ * In either case, a call to OEMCrypto_GetHDCPCapability() shall return the
+ * current HDCP level.
+ *
+ * #### Bypass Decrypt
+ *
+ * Platforms that wish to support Bypass Decrypt are still required to implement
+ * this function so that the decrypt path can be tested. It is acceptable for
+ * this function to invoke the bypass mechanism instead of calling into the
+ * OEMCrypto TA. For more information on Bypass Decrypt, see the
+ * [Bypass Decrypt](../../bypass) documentation.
+ *
+ * #### Non-Bypass Decrypt
+ *
+ * For platforms that do not need to support Bypass Decrypt, a mode compatible
+ * with previous versions of OEMCrypto is available. The "key handle" created by
+ * OEMCrypto_GetKeyHandle() is the session ID, as described above, and can be
+ * used the same as the session ID previously passed to OEMCrypto_DecryptCENC().
+ *
+ * If the device is not bypassing, it must update the ODK clock values in this
+ * function call. If this is the first use of a key for this session, then
+ * OEMCrypto shall call ODK_AttemptFirstPlayback to update the session's clock
+ * values and verify playback is allowed. If this is not the first use of a key
+ * for this session, then OEMCrypto shall call ODK_UpdateLastPlaybackTime. See
+ * [ODK Clocks and Timers](../../odk-timers) for handling the return value of
+ * these ODK functions.
+ *
+ * @param[in] key_handle: pointer to a buffer containing the key handle for a
+ * key previously installed with OEMCrypto_GetKeyHandle().
+ * @param[in] key_handle_length: length of the data in the key_handle buffer, in
+ * bytes.
+ * @param[in] samples: A caller-owned array of OEMCrypto_SampleDescription
+ * structures. Each entry in this array contains one sample of the content.
+ * @param[in] samples_length: The length of the array pointed to by the samples
+ * parameter.
+ * @param[in] pattern: A caller-owned structure indicating the encrypt/skip
+ * pattern as specified in the ISO-CENC standard.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_DECRYPT_FAILED
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_HDCP
+ * @retval OEMCrypto_ERROR_ANALOG_OUTPUT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE if the input buffer is too large,
+ * and should be partitioned.
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the destination buffer is shorter
+ * than the source
+ * @retval OEMCrypto_ERROR_OUTPUT_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ * @retval OEMCrypto_ERROR_UNSUPPORTED_CIPHER
+ *
+ * @buffer_size
+ * OEMCrypto shall support subsample sizes and total input buffer sizes as
+ * specified by its resource rating tier.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size. If OEMCrypto returns
+ * OEMCrypto_ERROR_BUFFER_TOO_LARGE, the CDM will break the buffer into
+ * smaller chunks. For high performance devices, OEMCrypto should handle
+ * larger buffers. We encourage OEMCrypto implementers not to artificially
+ * restrict the maximum buffer size.
+ * If OEMCrypto detects that the output data is too large, and breaking the
+ * buffer into smaller subsamples will not work, then it returns
+ * OEMCrypto_ERROR_OUTPUT_TOO_LARGE. This error will bubble up to the
+ * application, which can decide to skip the current frame of video or to
+ * switch to a lower resolution.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for the session containing the key. It will not be called simultaneously
+ * with initialization or usage table functions. It is as if the CDM holds a
+ * write lock for the key's session, and a read lock on the OEMCrypto system.
+ *
+ * The threading guarantees for this function are only guaranteed when the
+ * function is called through the Widevine CDM. If the platform uses Bypass
+ * Decrypt in a way that still calls this function, the OS may call this
+ * function in ways that violate these threading guarantees.
+ *
+ * @version
+ * This method changed in API version 18. This method changed its name in API
+ * version 11.
+ */
+OEMCryptoResult OEMCrypto_DecryptCENC(
+ const uint8_t* key_handle, size_t key_handle_length,
+ const OEMCrypto_SampleDescription* samples, // an array of samples.
+ size_t samples_length, // the number of samples.
+ const OEMCrypto_CENCEncryptPatternDesc* pattern);
+
+/**
+ * Copies the payload in the buffer referenced by the *data parameter into
+ * the buffer referenced by the out_buffer parameter. The data is simply
+ * copied. The definition of OEMCrypto_DestBufferDesc and subsample_flags are
+ * the same as in OEMCrypto_DecryptCENC(), above.
+ *
+ * The main difference between this and DecryptCENC is that this function may be
+ * used before a license is loaded into a session. In particular, an application
+ * will use this to copy the clear leader of a video to a secure buffer while
+ * the license request is being generated, sent to the server, and the response
+ * is being processed. This functionality is needed because an application may
+ * not have read or write access to a secure destination buffer.
+ *
+ * NOTES:
+ *
+ * This method may be called several times before the data is used. The first
+ * buffer in a chunk of data will have the OEMCrypto_FirstSubsample bit set
+ * in subsample_flags. The last buffer in a chunk of data will have the
+ * OEMCrypto_LastSubsample bit set in subsample_flags. The data will not be
+ * used until after OEMCrypto_LastSubsample has been set. If an
+ * implementation copies data immediately, it may ignore subsample_flags.
+ *
+ * If the destination buffer is secure, an offset may be specified.
+ * CopyBuffer begins storing data out_buffer->secure.offset bytes after the
+ * beginning of the secure buffer.
+ *
+ * @verification
+ * The following checks should be performed.
+ * 1. If either data or out_buffer is null, return
+ * OEMCrypto_ERROR_INVALID_CONTEXT.
+ *
+ * @param[in] session: crypto session identifier.
+ * @param[in] data_addr: An unaligned pointer to the buffer to be copied.
+ * @param[in] data_addr_length: The length of the buffer, in bytes.
+ * @param[in] out_buffer_descriptor: A caller-owned descriptor that specifies
+ * the handling of the byte stream. See OEMCrypto_DestBufferDesc for details.
+ * @param[in] subsample_flags: bitwise flags indicating if this is the first,
+ * middle, or last subsample in a chunk of data. 1 = first subsample, 2 =
+ * last subsample, 3 = both first and last subsample, 0 = neither first nor
+ * last subsample.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE if the input buffer is too large,
+ * and should be partitioned.
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the destination buffer is shorter
+ * than the source
+ * @retval OEMCrypto_ERROR_OUTPUT_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support subsample sizes and sample sizes as specified in
+ * OEMCrypto_ResourceRatingTier(). This function will only be given a single
+ * sample. OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the
+ * buffer is larger than the supported size. If OEMCrypto returns
+ * OEMCrypto_ERROR_BUFFER_TOO_LARGE, the calling function must break the
+ * buffer into smaller chunks. For high performance devices, OEMCrypto should
+ * handle larger buffers. We encourage OEMCrypto implementers not to
+ * artificially restrict the maximum buffer size. If OEMCrypto detects that
+ * the output data is too large, and breaking the buffer into smaller
+ * subsamples will not work, then it returns
+ * OEMCrypto_ERROR_OUTPUT_TOO_LARGE. This error will bubble up to the
+ * application, which can decide to skip the current frame of video or to
+ * switch to a lower resolution.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is changed in API version 15.
+ */
+OEMCryptoResult OEMCrypto_CopyBuffer(
+ OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* data_addr,
+ size_t data_addr_length,
+ const OEMCrypto_DestBufferDesc* out_buffer_descriptor,
+ uint8_t subsample_flags);
+
+/**
+ * This function encrypts a generic buffer of data using the given key.
+ *
+ * OEMCrypto shall be able to handle buffers at least 100 KiB long.
+ *
+ * #### Bypass Decrypt
+ *
+ * Platforms that wish to support Bypass Decrypt are still required to implement
+ * this function. For more information on Bypass Decrypt, see the
+ * [Bypass Decrypt](../../bypass) documentation.
+ *
+ * #### Non-Bypass Decrypt
+ *
+ * For platforms that do not need to support Bypass Decrypt, a mode compatible
+ * with previous versions of OEMCrypto is available. The "key handle" created by
+ * OEMCrypto_GetKeyHandle() is the session ID, as described above, and can be
+ * used the same as the session ID previously passed to OEMCrypto_DecryptCENC().
+ *
+ * If the device is not bypassing, it must update the ODK clock values in this
+ * function call. If this is the first use of a key for this session, then
+ * OEMCrypto shall call ODK_AttemptFirstPlayback to update the session's clock
+ * values and verify playback is allowed. If this is not the first use of a key
+ * for this session, then OEMCrypto shall call ODK_UpdateLastPlaybackTime. See
+ * [ODK Clocks and Timers](../../odk-timers) for handling the return value of
+ * these ODK functions.
+ *
+ * @verification
+ * The following checks should be performed. If any check fails, an error is
+ * returned, and the data is not encrypted.
+ * 1. The control bit for the key shall have the Allow_Encrypt set. If not,
+ * return OEMCrypto_ERROR_UNKNOWN_FAILURE.
+ * 2. If the key has an entry in the Usage Table, and the status of that
+ * entry is either kInactiveUsed or kInactiveUnused, then return the
+ * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ *
+ * @param[in] key_handle: pointer to a buffer containing the key handle for a
+ * key previously installed with OEMCrypto_GetKeyHandle().
+ * @param[in] key_handle_length: length of the data in the key_handle buffer, in
+ * bytes.
+ * @param[in] in_buffer: pointer to memory containing data to be encrypted.
+ * @param[in] in_buffer_length: length of the buffer, in bytes. The algorithm
+ * may restrict in_buffer_length to be a multiple of block size.
+ * @param[in] iv: IV for encrypting data. Size is 128 bits.
+ * @param[in] algorithm: Specifies which encryption algorithm to use.
+ * Currently, only CBC 128 mode is allowed for encryption.
+ * @param[out] out_buffer: pointer to buffer in which encrypted data should be
+ * stored.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @buffer_size
+ * OEMCrypto shall support buffer sizes of at least 100 KiB for generic
+ * crypto operations.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for the session containing the key. It will not be called simultaneously
+ * with initialization or usage table functions. It is as if the CDM holds a
+ * write lock for the key's session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 18.
+ */
+OEMCryptoResult OEMCrypto_Generic_Encrypt(
+ const uint8_t* key_handle, size_t key_handle_length,
+ const OEMCrypto_SharedMemory* in_buffer, size_t in_buffer_length,
+ const uint8_t* iv, OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* out_buffer);
+
+/**
+ * This function decrypts a generic buffer of data using the given key.
+ *
+ * OEMCrypto should be able to handle buffers at least 100 KiB long.
+ *
+ * #### Bypass Decrypt
+ *
+ * Platforms that wish to support Bypass Decrypt are still required to implement
+ * this function. For more information on Bypass Decrypt, see the
+ * [Bypass Decrypt](../../bypass) documentation.
+ *
+ * #### Non-Bypass Decrypt
+ *
+ * For platforms that do not need to support Bypass Decrypt, a mode compatible
+ * with previous versions of OEMCrypto is available. The "key handle" created by
+ * OEMCrypto_GetKeyHandle() is the session ID, as described above, and can be
+ * used the same as the session ID previously passed to OEMCrypto_DecryptCENC().
+ *
+ * If the device is not bypassing, it must update the ODK clock values in this
+ * function call. If this is the first use of a key for this session, then
+ * OEMCrypto shall call ODK_AttemptFirstPlayback to update the session's clock
+ * values and verify playback is allowed. If this is not the first use of a key
+ * for this session, then OEMCrypto shall call ODK_UpdateLastPlaybackTime. See
+ * [ODK Clocks and Timers](../../odk-timers) for handling the return value of
+ * these ODK functions.
+ *
+ * @verification
+ * The following checks should be performed. If any check fails, an error is
+ * returned, and the data is not decrypted.
+ * 1. The control bit for the key shall have the Allow_Decrypt set. If not,
+ * return OEMCrypto_ERROR_DECRYPT_FAILED.
+ * 2. If the key's control block has the Data_Path_Type bit set, then return
+ * OEMCrypto_ERROR_DECRYPT_FAILED.
+ * 3. If the key has an entry in the Usage Table, and the status of that
+ * entry is either kInactiveUsed or kInactiveUnused, then return the
+ * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ *
+ * @param[in] key_handle: pointer to a buffer containing the key handle for a
+ * key previously installed with OEMCrypto_GetKeyHandle().
+ * @param[in] key_handle_length: length of the data in the key_handle buffer, in
+ * bytes.
+ * @param[in] in_buffer: pointer to memory containing data to be encrypted.
+ * @param[in] in_buffer_length: length of the buffer, in bytes. The algorithm
+ * may restrict in_buffer_length to be a multiple of block size.
+ * @param[in] iv: IV for encrypting data. Size is 128 bits.
+ * @param[in] algorithm: Specifies which encryption algorithm to use.
+ * Currently, only CBC 128 mode is allowed for decryption.
+ * @param[out] out_buffer: pointer to buffer in which decrypted data should be
+ * stored.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ * @retval OEMCrypto_ERROR_DECRYPT_FAILED
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @buffer_size
+ * OEMCrypto shall support buffer sizes of at least 100 KiB for generic
+ * crypto operations.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for the session containing the key. It will not be called simultaneously
+ * with initialization or usage table functions. It is as if the CDM holds a
+ * write lock for the key's session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 18.
+ */
+OEMCryptoResult OEMCrypto_Generic_Decrypt(
+ const uint8_t* key_handle, size_t key_handle_length,
+ const OEMCrypto_SharedMemory* in_buffer, size_t in_buffer_length,
+ const uint8_t* iv, OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* out_buffer);
+
+/**
+ * This function signs a generic buffer of data using the given key.
+ *
+ * #### Bypass Decrypt
+ *
+ * Platforms that wish to support Bypass Decrypt are still required to implement
+ * this function. For more information on Bypass Decrypt, see the
+ * [Bypass Decrypt](../../bypass) documentation.
+ *
+ * #### Non-Bypass Decrypt
+ *
+ * For platforms that do not need to support Bypass Decrypt, a mode compatible
+ * with previous versions of OEMCrypto is available. The "key handle" created by
+ * OEMCrypto_GetKeyHandle() is the session ID, as described above, and can be
+ * used the same as the session ID previously passed to OEMCrypto_DecryptCENC().
+ *
+ * If the device is not bypassing, it must update the ODK clock values in this
+ * function call. If this is the first use of a key for this session, then
+ * OEMCrypto shall call ODK_AttemptFirstPlayback to update the session's clock
+ * values and verify playback is allowed. If this is not the first use of a key
+ * for this session, then OEMCrypto shall call ODK_UpdateLastPlaybackTime. See
+ * [ODK Clocks and Timers](../../odk-timers) for handling the return value of
+ * these ODK functions.
+ *
+ * @verification
+ * The following checks should be performed. If any check fails, an error is
+ * returned, and the data is not signed.
+ * 1. The control bit for the key shall have the Allow_Sign set.
+ * 2. If the key has an entry in the Usage Table, and the status of that
+ * entry is either kInactiveUsed or kInactiveUnused, then return the
+ * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ *
+ * @param[in] key_handle: pointer to a buffer containing the key handle for a
+ * key previously installed with OEMCrypto_GetKeyHandle().
+ * @param[in] key_handle_length: length of the data in the key_handle buffer, in
+ * bytes.
+ * @param[in] buffer: pointer to memory containing data to be encrypted.
+ * @param[in] buffer_length: length of the buffer, in bytes.
+ * @param[in] algorithm: Specifies which algorithm to use.
+ * @param[out] signature: pointer to buffer in which signature should be
+ * stored. May be null on the first call in order to find required buffer
+ * size.
+ * @param[in,out] signature_length: (in) length of the signature buffer, in
+ * bytes. (out) actual length of the signature
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if signature buffer is not large enough
+ * to hold the output signature.
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @buffer_size
+ * OEMCrypto shall support buffer sizes of at least 100 KiB for generic
+ * crypto operations.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for the session containing the key. It will not be called simultaneously
+ * with initialization or usage table functions. It is as if the CDM holds a
+ * write lock for the key's session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 18.
+ */
+OEMCryptoResult OEMCrypto_Generic_Sign(const uint8_t* key_handle,
+ size_t key_handle_length,
+ const OEMCrypto_SharedMemory* buffer,
+ size_t buffer_length,
+ OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* signature,
+ size_t* signature_length);
+
+/**
+ * This function verifies the signature of a generic buffer of data using the
+ * given key.
+ *
+ * #### Bypass Decrypt
+ *
+ * Platforms that wish to support Bypass Decrypt are still required to implement
+ * this function. For more information on Bypass Decrypt, see the
+ * [Bypass Decrypt](../../bypass) documentation.
+ *
+ * #### Non-Bypass Decrypt
+ *
+ * For platforms that do not need to support Bypass Decrypt, a mode compatible
+ * with previous versions of OEMCrypto is available. The "key handle" created by
+ * OEMCrypto_GetKeyHandle() is the session ID, as described above, and can be
+ * used the same as the session ID previously passed to OEMCrypto_DecryptCENC().
+ *
+ * If the device is not bypassing, it must update the ODK clock values in this
+ * function call. If this is the first use of a key for this session, then
+ * OEMCrypto shall call ODK_AttemptFirstPlayback to update the session's clock
+ * values and verify playback is allowed. If this is not the first use of a key
+ * for this session, then OEMCrypto shall call ODK_UpdateLastPlaybackTime. See
+ * [ODK Clocks and Timers](../../odk-timers) for handling the return value of
+ * these ODK functions.
+ *
+ * @verification
+ * The following checks should be performed. If any check fails, an error is
+ * returned.
+ * 1. The control bit for the key shall have the Allow_Verify set.
+ * 2. The signature of the message shall be computed, and the API shall
+ * verify the computed signature matches the signature passed in. If
+ * not, return OEMCrypto_ERROR_SIGNATURE_FAILURE.
+ * 3. The signature verification shall use a constant-time algorithm (a
+ * signature mismatch will always take the same time as a successful
+ * comparison).
+ * 4. If the key has an entry in the Usage Table, and the status of that
+ * entry is either kInactiveUsed or kInactiveUnused, then return the
+ * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ *
+ * @param[in] key_handle: pointer to a buffer containing the key handle for a
+ * key previously installed with OEMCrypto_GetKeyHandle().
+ * @param[in] key_handle_length: length of the data in the key_handle buffer, in
+ * bytes.
+ * @param[in] buffer: pointer to memory containing data to be encrypted.
+ * @param[in] buffer_length: length of the buffer, in bytes.
+ * @param[in] algorithm: Specifies which algorithm to use.
+ * @param[in] signature: pointer to buffer in which signature resides.
+ * @param[in] signature_length: length of the signature buffer, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_KEY_EXPIRED
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION
+ *
+ * @buffer_size
+ * OEMCrypto shall support buffer sizes of at least 100 KiB for generic
+ * crypto operations.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for the session containing the key. It will not be called simultaneously
+ * with initialization or usage table functions. It is as if the CDM holds a
+ * write lock for the key's session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 18.
+ */
+OEMCryptoResult OEMCrypto_Generic_Verify(
+ const uint8_t* key_handle, size_t key_handle_length,
+ const OEMCrypto_SharedMemory* buffer, size_t buffer_length,
+ OEMCrypto_Algorithm algorithm, const OEMCrypto_SharedMemory* signature,
+ size_t signature_length);
+
+/// @}
+
+/// @addtogroup factory_provision
+/// @{
+
+/**
+ * A device should be provisioned at the factory with either an OEM
+ * Certificate or a keybox. We will call this data the root of trust. During
+ * manufacturing, the root of trust should be encrypted with the OEM root key
+ * and stored on the file system in a region that will not be erased during
+ * factory reset. This function may be used by legacy systems that use the
+ * two-step WrapKeyboxOrOEMCert()/InstallKeyboxOrOEMCert() approach. When the
+ * Widevine DRM plugin initializes, it will look for a wrapped root of trust
+ * in the file /factory/wv.keys and install it into the security processor by
+ * calling OEMCrypto_InstallKeyboxOrOEMCert().
+ *
+ * 
+ *
+ * OEMCrypto_WrapKeyboxOrOEMCert() is used to generate an OEM-encrypted root
+ * of trust that may be passed to OEMCrypto_InstallKeyboxOrOEMCert() for
+ * provisioning. The root of trust may be either passed in the clear or
+ * previously encrypted with a transport key. If a transport key is supplied,
+ * the keybox is first decrypted with the transport key before being wrapped
+ * with the OEM root key. This function is only needed if the root of trust
+ * provisioning method involves saving the keybox or OEM Certificate to the
+ * file system.
+ *
+ * @param[in] keybox_or_cert: pointer to root of trust data to encrypt -- this
+ * is either a keybox or an OEM Certificate private key. May be NULL on the
+ * first call to test the size of the wrapped keybox. The keybox may either
+ * be clear or previously encrypted.
+ * @param[in] keybox_or_cert_length: length the keybox or cert data in bytes
+ * @param[out] wrapped_keybox_or_cert: Pointer to wrapped keybox or cert
+ * @param[in,out] wrapped_keybox_or_cert_length: Pointer to the length of the
+ * wrapped keybox or certificate key in bytes
+ * @param[in] transport_key: Optional. AES transport key. If provided, the
+ * keybox_or_cert parameter was previously encrypted with this key. The
+ * keybox will be decrypted with the transport key using AES-CBC and a null
+ * IV.
+ * @param[in] transport_key_length: Optional. Number of bytes in the
+ * transport_key, if used.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_WRITE_KEYBOX failed to encrypt the keybox
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if keybox is provided as NULL, to
+ * determine the size of the wrapped keybox
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is supported in all API versions.
+ */
+OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert(
+ const uint8_t* keybox_or_cert, size_t keybox_or_cert_length,
+ uint8_t* wrapped_keybox_or_cert, size_t* wrapped_keybox_or_cert_length,
+ const uint8_t* transport_key, size_t transport_key_length);
+
+/**
+ * Decrypts a wrapped root of trust and installs it in the security
+ * processor. The root of trust is unwrapped then encrypted with the OEM root
+ * key. This function is called from the Widevine DRM plugin at
+ * initialization time if there is no valid root of trust installed. It looks
+ * for wrapped data in the file /factory/wv.keys and if it is present, will
+ * read the file and call OEMCrypto_InstallKeyboxOrOEMCert() with the
+ * contents of the file. This function is only needed if the factory
+ * provisioning method involves saving the keybox or OEM Certificate to the
+ * file system.
+ *
+ * 
+ *
+ * @param[in] keybox_or_cert: pointer to encrypted data as input
+ * @param[in] keybox_or_cert_length: length of the data in bytes
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_BAD_MAGIC
+ * @retval OEMCrypto_ERROR_BAD_CRC
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is supported in all API versions.
+ */
+OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* keybox_or_cert,
+ size_t keybox_or_cert_length);
+
+/**
+ * Install a factory generated signature for the BCC. This is for devices that
+ * use Provisioning 4.0, with the signing option in the factory. With the
+ * signing option, the BCC is extracted from the device in the factory. Instead
+ * of being uploaded to the Widevine server, the BCC is signed by a certificate
+ * that the manufacturer shares with Widevine. The signature is then installed
+ * on the device is a secure location. The signature must not be erased during
+ * factory reset.
+ *
+ * This signature should be returned as `addition_signature` in a call to the
+ * function `OEMCrypto_GetBootCertificateChain()`.
+ *
+ * Devices that do not support Provisioning 4.0, or only support Provisioning
+ * 4.0 Option 1 should return OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ *
+ * @param[in] signature: pointer to data as input
+ * @param[in] signature_length: length of the data in bytes
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 18.3.
+ */
+OEMCryptoResult OEMCrypto_FactoryInstallBCCSignature(const uint8_t* signature,
+ size_t signature_length);
+
+/**
+ * This function is for OEMCrypto to tell the layer above what provisioning
+ * method it uses: keybox or OEM certificate.
+ *
+ * @retval OEMCrypto_DrmCertificate means the device has a DRM certificate built
+ * into the system. This cannot be used by level 1 devices. This
+ * provisioning method is deprecated and should not be used on new
+ * devices. OEMCertificate provisioning should be used instead.
+ * @retval OEMCrypto_Keybox means the device has a unique keybox. For level 1
+ * devices this keybox must be securely installed by the device
+ * manufacturer.
+ * @retval OEMCrypto_OEMCertificate means the device has a factory installed OEM
+ * certificate. This is also called Provisioning 3.0.
+ * @retval OEMCrypto_ProvisioningError indicates a serious problem with the
+ * OEMCrypto library.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new API version 12.
+ */
+OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod(void);
+
+/**
+ * If the device has a keybox, this validates the Widevine Keybox loaded into
+ * the security processor device. This method verifies two fields in the
+ * keybox:
+ *
+ * - Verify the MAGIC field contains a valid signature (such as,
+ * 'k''b''o''x').
+ * - Compute the CRC using CRC-32-POSIX-1003.2 standard and compare the
+ * checksum to the CRC stored in the Keybox.
+ * The CRC is computed over the entire Keybox excluding the 4 bytes of the
+ * CRC (for example, Keybox[0..123]). For a description of the fields stored
+ * in the keybox, see Keybox Definition in the
+ * [Provisioning 2.0](../../index#prov20) section of the integration guide.
+ *
+ * If the device has an OEM Certificate, this validates the certificate
+ * private key.
+ *
+ * On devices that support OEMCrypto_GenerateOTARequest() and
+ * OEMCrypto_ProcessOTAKeybox(), this function may return
+ * OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING when a valid keybox is not present.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_BAD_MAGIC
+ * @retval OEMCrypto_ERROR_BAD_CRC
+ * @retval OEMCrypto_ERROR_KEYBOX_INVALID
+ * @retval OEMCrypto_ERROR_INVALID_KEY
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is supported in all API versions.
+ */
+OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void);
+
+/**
+ * Return a device unique id. For devices with a keybox, retrieve the
+ * DeviceID from the Keybox. For devices that have an OEM Certificate, or if
+ * provisioning 4 is used, it should set the device ID to a device-unique
+ * string, such as the device serial number or a hash of the device public key
+ * in boot certificate chain. The ID should be device-unique and it should be
+ * stable -- i.e. it should not change across a device reboot or a system
+ * upgrade. This shall match the device id found in the core provisioning
+ * request message. The maximum length of the device id is 64 bytes. The
+ * device ID field in a keybox is 32 bytes.
+ *
+ * @param[out] device_id: pointer to the buffer that receives the Device ID.
+ * @param[in,out] device_id_length - on input, size of the caller's device ID
+ * buffer. On output, the number of bytes written into the buffer.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return
+ * device ID
+ * @retval OEMCrypto_ERROR_NO_DEVICEID failed to return Device Id
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is supported in all API versions.
+ */
+OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* device_id,
+ size_t* device_id_length);
+
+/// @}
+
+/// @addtogroup keybox
+/// @{
+
+/**
+ * Return the Key Data field from the Keybox.
+ *
+ * @param[out] key_data: pointer to the buffer to hold the Key Data field from
+ * the Keybox
+ * @param[in,out] key_data_length: on input, the allocated buffer size. On
+ * output, the number of bytes in Key Data
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return
+ * KeyData
+ * @retval OEMCrypto_ERROR_NO_KEYDATA
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED: this function is for
+ * Provisioning 2.0 only.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is supported in all API versions.
+ */
+OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* key_data,
+ size_t* key_data_length);
+
+/// @}
+
+/// @addtogroup test_verify
+/// @{
+/**
+ * Temporarily use the specified test keybox until the next call to
+ * OEMCrypto_Terminate(). This allows a standard suite of unit tests to be run
+ * on a production device without permanently changing the keybox. Using the
+ * test keybox is not persistent. OEMCrypto cannot assume that this keybox is
+ * the same as previous keyboxes used for testing.
+ *
+ * Devices that use an OEM Certificate instead of a keybox (i.e. Provisioning
+ * 3.0) do not need to support this functionality, and may return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @param[in] buffer: pointer to memory containing test keybox, in binary form.
+ * @param[in] buffer_length: length of the buffer, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED this function is for
+ * Provisioning 2.0 only.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system. It is called after OEMCrypto_Initialize() and
+ * after OEMCrypto_GetProvisioningMethod() and only if the provisoining method
+ * is OEMCrypto_Keybox,
+ *
+ * @version
+ * This method changed in API version 14.
+ */
+OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
+ size_t buffer_length);
+
+/// @}
+
+/// @addtogroup oem_cert
+/// @{
+/**
+ * After a call to this function, all session functions using an RSA key
+ * should use the OEM certificate's private RSA key. See the section
+ * discussing [Provisioning 3.0](../../index#prov30) section of the integration
+ * guide.
+ *
+ * @param[in] session: this function affects the specified session only.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED this function is for
+ * Provisioning 3.0 only.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new API version 16.
+ */
+OEMCryptoResult OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session);
+
+/**
+ * This function should place the OEM public certificate in the buffer
+ * public_cert. See the section discussing
+ * [Provisioning 3.0](../../index#prov30) section of the integration guide.
+ *
+ * If the buffer is not large enough, OEMCrypto should update
+ * public_cert_length and return OEMCrypto_ERROR_SHORT_BUFFER.
+ *
+ * @param[out] public_cert: the buffer where the public certificate is stored.
+ * @param[in,out] public_cert_length: on input, this is the available size of
+ * the buffer. On output, this is the number of bytes needed for the
+ * certificate.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED this function is for
+ * Provisioning 3.0 only.
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new API version 16.
+ */
+OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(uint8_t* public_cert,
+ size_t* public_cert_length);
+
+/// @}
+
+/// @addtogroup validation
+/// @{
+/** Specifies OEMCrypto security level.
+ */
+typedef enum OEMCrypto_Security_Level {
+ OEMCrypto_Level_Unknown = 0,
+ OEMCrypto_Level1 = 1,
+ OEMCrypto_Level2 = 2,
+ OEMCrypto_Level3 = 3,
+} OEMCrypto_Security_Level;
+
+/**
+ * This function returns the current API version number. The version number
+ * allows the calling application to avoid version mis-match errors, because
+ * this API is part of a shared library.
+ *
+ * There is a possibility that some API methods will be backwards compatible,
+ * or backwards compatible at a reduced security level.
+ *
+ * There is no plan to introduce forward-compatibility. Applications will
+ * reject a library with a newer version of the API.
+ *
+ * The version specified in this document is 16. Any OEM that returns this
+ * version number guarantees it passes all unit tests associated with this
+ * version.
+ *
+ * @return
+ * The supported API, as specified in the header file OEMCryptoCENC.h.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in each API version.
+ */
+uint32_t OEMCrypto_APIVersion(void);
+
+/**
+ * This function returns the current API minor version number. The version
+ * number allows the calling application to avoid version mis-match errors,
+ * because this API is part of a shared library.
+ *
+ * The minor version specified in this document is 2. Any OEM that returns
+ * this version number guarantees it passes all unit tests associated with
+ * this version.
+ *
+ * @return
+ * The supported API, as specified in the header file OEMCryptoCENC.h.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in each API version.
+ */
+uint32_t OEMCrypto_MinorAPIVersion(void);
+
+/**
+ * Stores the build information of the OEMCrypto library in a buffer. This
+ * string should be updated with each release or OEMCrypto build.
+ *
+ * It may be used for logging or bug tracking and may be bubbled up to the
+ * app so that it may track metrics on errors.
+ *
+ * The returned string must be JSON formatted. It shall also contain the
+ * following top level values [data types in brackets]:
+ * - "soc_vendor" [string]: SOC manufacturer name
+ * - "soc_model" [string]: SOC model name
+ * - "ta_ver" [string]: TA version in string format eg "1.12.3+tag", "2.0"
+ * - "uses_opk" [bool]: Whether TA was built with Widevine's OPK
+ * - "tee_os" [string]: Trusted OS intended to run the TA, eg "Trusty", "QSEE",
+ * "OP-TEE"
+ * - "tee_os_ver" [string]: Version of Trusted OS intended to run the TA
+ * - "is_debug" [bool]: Whether this is a debug build of the TA. Debug builds
+ * can enter Test Mode via OEMCrypto_EnterTestMode(), while production builds
+ * cannot. Debug builds are not released to the public.
+ *
+ * While not required, the following top level fields are recommended:
+ * - "implementer" [string]: Name of company or entity that provides OEMCrypto.
+ * Important if not SOC vendor.
+ * - "git_commit" [string]: Git commit hash of the code repository that
+ * produced the TA build. Useful for implementers to distinguish the state of
+ * different TA builds.
+ * - "build_timestamp" [string]: ISO 8601 formatted timestamp of the time the
+ * TA was compiled, eg "YYYY-MM-DDTHH:MM:SS"
+ * - "is_factory_mode" [bool]: Whether this was built with FACTORY_MODE_ONLY
+ * defined
+ *
+ * While not required, another optional top level struct can be added to the
+ * build information string to provide information about liboemcrypto.so:
+ * - "ree" {
+ * - "liboemcrypto_ver" [string]: liboemcrypto.so version in string format
+ * eg "2.15.0+tag". Note that this is separate from the "ta_ver" field
+ * above, since this section is specific to the liboemcrypto.so binary.
+ * - "git_commit" [string]: git hash of code that compiled liboemcrypto.so
+ * - "build_timestamp" [string]: ISO 8601 timestamp for when
+ * liboemcrypto.so was built
+ * }
+ *
+ * The JSON string can contain other values, structs, arrays, etc in addition to
+ * the above, if desired.
+ *
+ * If buffer_length is not enough, the function will return
+ * OEMCrypto_ERROR_SHORT_BUFFER. Before returning OEMCrypto_ERROR_SHORT_BUFFER,
+ * the function should set buffer_length to the length of buffer needed. If the
+ * write is successful, buffer_length will be set to the number of bytes
+ * written.
+ *
+ * The returned data shall be no larger than 1024 bytes. If the buffer length is
+ * larger, this function will return OEMCrypto_ERROR_BUFFER_TOO_LARGE and set
+ * |buffer_length| to 1024.
+ *
+ * @param[out] buffer: pointer to the buffer that receives build information
+ * @param[in,out] buffer_length: length of the data buffer in bytes
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small.
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is too large.
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE any other failure.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in each API version.
+ */
+OEMCryptoResult OEMCrypto_BuildInformation(char* buffer, size_t* buffer_length);
+
+/**
+ * This function returns the current patch level of the software running in
+ * the trusted environment. The patch level is defined by the OEM, and is
+ * only incremented when a security update has been added.
+ *
+ * See the section [Security Patch Level](../../index#security_patch_level)
+ * for more details.
+ *
+ * @return
+ * The OEM defined version number.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method was introduced in API version 11.
+ */
+uint8_t OEMCrypto_Security_Patch_Level(void);
+
+/**
+ * Returns a string specifying the security level of the library.
+ *
+ * Since this function is spoofable, it is not relied on for security
+ * purposes. It is for information only.
+ *
+ * @return A security level enum. Values are OEMCrypto_Level_Unknown,
+ * OEMCrypto_Level1, OEMCrypto_Level2 and OEMCrypto_Level3.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 17.
+ */
+OEMCrypto_Security_Level OEMCrypto_SecurityLevel(void);
+
+/**
+ * Returns the maximum HDCP version supported by the device, and the HDCP
+ * version supported by the device and any connected display.
+ *
+ * Valid values for HDCP_Capability are:
+ *
+ * The value 0xFF means the device is using a local, secure, data path
+ * instead of HDMI output. Notice that HDCP must use flag Type 1: all
+ * downstream devices will also use the same version or higher.
+ *
+ * The maximum HDCP level should be the maximum value that the device can
+ * enforce. For example, if the device has an HDCP 1.0 port and an HDCP 2.0
+ * port, and the first port can be disabled, then the maximum is HDCP 2.0. If
+ * the first port cannot be disabled, then the maximum is HDCP 1.0. The
+ * maximum value can be used by the application or server to decide if a
+ * license may be used in the future. For example, a device may be connected
+ * to an external display while an offline license is downloaded, but the
+ * user intends to view the content on a local display. The user will want to
+ * download the higher quality content.
+ *
+ * The current HDCP level should be the level of HDCP currently negotiated
+ * with any connected receivers or repeaters either through HDMI or a
+ * supported wireless format. If multiple ports are connected, the current
+ * level should be the minimum HDCP level of all ports. If the key control
+ * block requires an HDCP level equal to or lower than the current HDCP
+ * level, the key is expected to be usable. If the key control block requires
+ * a higher HDCP level, the key is expected to be forbidden.
+ *
+ * When a key has version HDCP_V2_3 required in the key control block, the
+ * transmitter must have HDCP version 2.3 and have negotiated a connection
+ * with a version 2.2 or 2.3 receiver or repeater. The transmitter must
+ * configure the content stream to be Type 1. Since the transmitter cannot
+ * distinguish between 2.2 and 2.3 downstream receivers when connected to a
+ * repeater, it may transmit to both 2.2 and 2.3 receivers, but not 2.1
+ * receivers.
+ *
+ * For example, if the transmitter is 2.3, and is connected to a receiver
+ * that supports 2.3 then the current level is HDCP_V2_3. If the transmitter
+ * is 2.3 and is connected to a 2.3 repeater, the current level is HDCP_V2_3
+ * even though the repeater can negotiate a connection with a 2.2 downstream
+ * receiver for a Type 1 Content Stream.
+ *
+ * As another example, if the transmitter can support 2.3, but a receiver
+ * supports 2.0, then the current level is HDCP_V2.
+ *
+ * When a license requires HDCP, a device may use a wireless protocol to
+ * connect to a display only if that protocol supports the version of HDCP as
+ * required by the license. Both WirelessHD (formerly WiFi Display) and
+ * Miracast support HDCP.
+ *
+ * @param[out] current: this is the current HDCP version, based on the device
+ * itself, and the display to which it is connected.
+ * @param[out] maximum: this is the maximum supported HDCP version for the
+ * device, ignoring any attached device.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 10.
+ */
+OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability* current,
+ OEMCrypto_HDCP_Capability* maximum);
+
+/**
+ * Returns the DTCP2 support for a device.
+ *
+ * @param[out] capability: this will be set to 0 if DTCP2 is not supported,
+ * and 1 if the device supports at least v1 of DTCO2.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_GetDTCP2Capability(
+ OEMCrypto_DTCP2_Capability* capability);
+
+/**
+ * This is used to determine if the device can support a usage table. Since
+ * this function is spoofable, it is not relied on for security purposes. It
+ * is for information only. The usage table is described in the section above.
+ *
+ * @return
+ * Returns true if the device can maintain a usage table. Returns false
+ * otherwise.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 9.
+ */
+bool OEMCrypto_SupportsUsageTable(void);
+
+/**
+ * Estimates the maximum usage table size. If the device does not have a
+ * fixed size, this returns an estimate. A maximum size of 0 means the header
+ * is constrained only by dynamic memory allocation.
+ *
+ * Widevine requires the size to be at least 300 entries.
+ *
+ * @return
+ * Returns an estimate for the maximum size of the usage table header.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+size_t OEMCrypto_MaximumUsageTableHeaderSize(void);
+
+/**
+ * Indicate whether there is hardware protection to detect and/or prevent the
+ * rollback of the usage table. For example, if the usage table contents is
+ * stored entirely on a secure file system that the user cannot read or write
+ * to. Another example is if the usage table has a generation number and the
+ * generation number is stored in secure memory that is not user accessible.
+ *
+ * @return Returns true if oemcrypto uses anti-rollback hardware. Returns false
+ * otherwise.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 10.
+ */
+bool OEMCrypto_IsAntiRollbackHwPresent(void);
+
+/**
+ * Returns the current number of open sessions. The CDM and OEMCrypto
+ * consumers can query this value so they can use resources more effectively.
+ *
+ * @param[out] count: this is the current number of opened sessions.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 10.
+ */
+OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count);
+
+/**
+ * Returns the maximum number of concurrent OEMCrypto sessions supported by
+ * the device. The CDM and OEMCrypto consumers can query this value so they
+ * can use resources more effectively. If the maximum number of sessions
+ * depends on a dynamically allocated shared resource, the returned value
+ * should be a best estimate of the maximum number of sessions.
+ *
+ * OEMCrypto shall support a minimum of 10 sessions. Some applications use
+ * multiple sessions to pre-fetch licenses, so high end devices should
+ * support more sessions -- we recommend a minimum of 50 sessions.
+ *
+ * @param[out] max: this is the max number of supported sessions.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 12.
+ */
+OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* max);
+
+/**
+ * Returns the type of certificates keys that this device supports. With very
+ * few exceptions, all devices should support at least 2048 bit RSA keys.
+ * High end devices should also support 3072 bit RSA keys. Devices that are
+ * cast receivers should also support RSA cast receiver certificates.
+ *
+ * Beginning with OEMCrypto v14, the provisioning server may deliver to the
+ * device an RSA key that uses the Carmichael totient. This does not change
+ * the RSA algorithm -- however the product of the private and public keys is
+ * not necessarily the Euler number \phi (n). OEMCrypto should not reject
+ * such keys.
+ *
+ * @return
+ * Returns the bitwise or of the following flags. It is likely that high end
+ * devices will support both 2048 and 3072 bit keys while the widevine
+ * servers transition to new key sizes.
+ * - 0x1 = OEMCrypto_Supports_RSA_2048bit - the device can load a DRM
+ * certificate with a 2048 bit RSA key.
+ * - 0x2 = OEMCrypto_Supports_RSA_3072bit - the device can load a DRM
+ * certificate with a 3072 bit RSA key.
+ * - 0x10 = OEMCrypto_Supports_RSA_CAST - the device can load a CAST
+ * certificate. These certificates are used with
+ * OEMCrypto_GenerateRSASignature() with padding type set to 0x2, PKCS1
+ * with block type 1 padding.
+ * - 0x100 = OEMCrypto_Supports_ECC_secp256r1 - Elliptic Curve secp256r1
+ * - 0x200 = OEMCrypto_Supports_ECC_secp384r1 - Elliptic Curve secp384r1
+ * - 0x400 = OEMCrypto_Supports_ECC_secp521r1 - Elliptic Curve secp521r1
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+uint32_t OEMCrypto_SupportedCertificates(void);
+
+/**
+ * Returns the version number of the current SRM file. If the device does not
+ * support SRM files, this will return OEMCrypto_ERROR_NOT_IMPLEMENTED. If
+ * the device only supports local displays, it would return
+ * OEMCrypto_LOCAL_DISPLAY_ONLY. If the device has an SRM, but cannot use
+ * OEMCrypto to update the SRM, then this function would set version to be
+ * the current version number, and return OEMCrypto_SUCCESS, but it would
+ * return false from OEMCrypto_IsSRMUpdateSupported().
+ *
+ * @param[out] version: current SRM version number.
+ *
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_LOCAL_DISPLAY_ONLY to indicate version was not set, and
+ * is not needed.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 13.
+ */
+OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(uint16_t* version);
+
+/**
+ * Returns whether the device supports analog output or not. This information
+ * will be sent to the license server, and may be used to determine the type
+ * of license allowed. This function is for reporting only. It is paired with
+ * the key control block flags Disable_Analog_Output and CGMS.
+ *
+ * @return
+ * Returns a bitwise OR of all possible return values.
+ * * 0x0 = OEMCrypto_No_Analog_Output: the device has no analog output.
+ * * 0x1 = OEMCrypto_Supports_Analog_Output: the device does have analog
+ * output.
+ * * 0x2 = OEMCrypto_Can_Disable_Analog_Ouptput: the device does have
+ * analog output, but it will disable analog output if required by the
+ * key control block.
+ * * 0x4 = OEMCrypto_Supports_CGMS_A: the device supports signaling 2-bit
+ * CGMS-A, if required by the key control block
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 14.
+ */
+uint32_t OEMCrypto_GetAnalogOutputFlags(void);
+
+/**
+ * This function returns a positive number indicating which resource rating
+ * it supports. This value will bubble up to the application level as a
+ * property. This will allow applications to estimate what resolution and
+ * bandwidth the device is expected to support.
+ *
+ * OEMCrypto unit tests and Android GTS tests will verify that devices do
+ * support the resource values specified in the table below at the tier
+ * claimed by the device. If a device claims to be a low end device, the
+ * OEMCrypto unit tests will only verify the low end performance values.
+ *
+ * OEMCrypto implementers should consider the numbers in the table to be minimum
+ * values.
+ *
+ * These performance parameters are for OEMCrypto only. In particular,
+ * bandwidth and codec resolution are determined by the platform.
+ *
+ * See the document [Resource Rating]
+ * (https://developers.google.com/widevine/drm/feature/resource-rating)
+ * for more information and for the table of parameters.
+ *
+ *
+ * Here is an additional note on the number of subsamples:
+ *
+ * The table specifies the number of subsamples that partition the content when
+ * it is encrypted. However, if OEMCrypto_DecryptCENC() returns
+ * OEMCrypto_ERROR_BUFFER_TOO_LARGE, the layer above OEMCrypto will break the
+ * sample into more subsamples.
+ *
+ * The minimum subsample buffer size is the smallest buffer that the CDM layer
+ * above OEMCrypto will use when breaking a sample into subsamples. As mentioned
+ * above, the CDM layer will only break a sample into smaller subsamples if
+ * OEMCrypto returns OEMCrypto_ERROR_BUFFER_TOO_LARGE. Because this might be a
+ * performance problem, OEMCrypto implementers are encouraged to process larger
+ * subsamples and to process multiple subsamples in a single call to
+ * DecryptCENC.
+ *
+ * The message size limit applies to all functions that sign or verify a
+ * message: OEMCrypto_PrepAndSignLicenseRequest(),
+ * OEMCrypto_PrepAndSignRenewalRequest(),
+ * OEMCrypto_PrepAndSignProvisioningRequest(), and OEMCrypto_LoadLicense(). A
+ * request message is also used as the context buffer in
+ * OEMCrypto_DeriveKeysFromSessionKey() and OEMCrypto_GenerateDerivedKeys().
+ *
+ *
+ * @return
+ * Returns an integer indicating which resource tier the device supports.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 15.
+ */
+uint32_t OEMCrypto_ResourceRatingTier(void);
+
+/**
+ * Returns OEMCrypto_SUCCESS if the device is production ready. This is a
+ * new reporting mechanism that reports that OEMCrypto is production ready.
+ * For example, the SOC delivers OEMCrypto to the OEM which functions
+ * correctly whether debugging or antirollback is turned on or not. The OEM
+ * has the option to turn on TEE software antirollback if they wish. If anti
+ * rollback is off, or if debugging is enabled, then this function will
+ * return failure.
+ *
+ * The OEMCrypto implementer may choose any other error code if the device
+ * is not production ready. The motivation for this new feature is to allow
+ * SOCs to signal to OEMs that hardening has not been done on a system.
+ * During development of a device, it is fine for this function to return an
+ * error. During development, we expect devices to have debugging turned on.
+ * However, once the device is ready for production, all hardening should be
+ * turned on.
+ *
+ * The intention is that certification tests, such as Android’s GTS test suite,
+ * will verify that a device is production ready. Being production ready will
+ * not be a requirement to pass OEMCrypto unit tests, but the status will be
+ * logged as part of the tests.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_ProductionReady(void);
+
+/**
+ * Returns OEMCrypto_WatermarkingAlwaysOn or OEMCrypto_WatermarkingConfigurable
+ * if the device supports watermarking. If the device does not support
+ * watermarking but the license has watermarking set to accept it,
+ * OEMCrypto_LoadLicense should return the error
+ * OEMCrypto_ERROR_INSUFFICIENT_PRIVILEGE, which is a new error code in v17.
+ *
+ * If watermarking can be turned on or off for individual streams, then
+ * OEMCrypto should honor the settings for each license individually.
+ *
+ * If watermarking can only be turned on or off on a system wide level, then
+ * the most recent license should be honored. The watermarking feature should
+ * be turned on or off when a license is loaded. If this conflicts with a
+ * license that had been loaded earlier, then keys from the earlier license may
+ * not be used. In this case, either OEMCrypto_GetKeyHandle or
+ * OEMCrypto_DecryptCENC will return OEMCrypto_ERROR_INSUFFICIENT_PRIVILEGE to
+ * indicate that the watermarking status has changed and the license is no
+ * longer usable.
+ *
+ * @retval OEMCrypto_WatermarkingError
+ * @retval OEMCrypto_WatermarkingNotSupported
+ * @retval OEMCrypto_WatermarkingConfigurable
+ * @retval OEMCrypto_WatermarkingAlwaysOn
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCrypto_WatermarkingSupport OEMCrypto_GetWatermarkingSupport(void);
+
+/**
+ * Queries the hash algorithm that the device will use when performing
+ * RSASSA-PSS or ECDSA with the private key currently loaded in the given
+ * session.
+ *
+ * For RSA keys, SHA-1 was used for all OEMCrypto versions prior to 18, but
+ * SHA-256 is strongly recommended for all devices. SHA-384 and SHA-512 are not
+ * supported with RSA keys.
+ *
+ * For ECC keys, the algorithm chosen depends on the curve used to generate the
+ * key, as outlined in the OEMCrypto Integration Guide. SHA-1 is not supported
+ * with ECC keys.
+ *
+ * For devices that do not support ECC, it is acceptable for this function to
+ * return a hardcoded value, since the answer does not depend on the currently
+ * loaded private key.
+ *
+ * @param[in] session: crypto session identifier.
+ * @param[out] algorithm: the algorithm the device will use.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 18.
+ */
+OEMCryptoResult OEMCrypto_GetSignatureHashAlgorithm(
+ OEMCrypto_SESSION session, OEMCrypto_SignatureHashAlgorithm* algorithm);
+
+/// @}
+
+/// @addtogroup drm_cert
+/// @{
+
+/**
+ * Load and parse a provisioning response, and then rewrap the private key
+ * for storage on the filesystem. We recommend that the OEM use an encryption
+ * key and signing key generated using an algorithm at least as strong as
+ * that in GenerateDerivedKeys.
+ *
+ * First, OEMCrypto shall verify the signature of the message using the correct
+ * algorithm depending on if the device supports Provisioning 2.0, 3.0 or 4.0.
+ *
+ * For Provisioning 2.0, OEMCrypto shall verify the signature of the message
+ * using HMAC-SHA256 with the derived mac_key[server]. The signature
+ * verification shall use a constant-time algorithm (a signature mismatch will
+ * always take the same time as a successful comparison). The signature is over
+ * the entire message buffer starting at message with length message_length. If
+ * the signature verification fails, ignore all other arguments and return
+ * OEMCrypto_ERROR_SIGNATURE_FAILURE.
+ *
+ * NOTE: The calling software must have previously established the mac_keys
+ * and encrypt_key with a call to OEMCrypto_DeriveKeysFromSessionKey() or
+ * OEMCrypto_GenerateDerivedKeys().
+ *
+ * For Provisioning 3.0 and 4.0, the signature is not verified.
+ *
+ * After the signature is verified,
+ * the function ODK_ParseProvisioning is called to parse the message. If it
+ * returns an error, OEMCrypto shall return that error to the CDM layer. The
+ * function ODK_ParseProvisioning is described in the document "Widevine Core
+ * Message Serialization".
+ *
+ * Below, all fields are found in the struct ODK_ParsedLicense parsed_license
+ * returned by ODK_ParsedProvisioning.
+ *
+ * After decrypting `parsed_response->enc_private_key`, If the first four bytes
+ * of the buffer are the string "SIGN", then the actual RSA key begins on the
+ * 9th byte of the buffer. The second four bytes of the buffer is the 32 bit
+ * field "allowed_schemes" of type RSA_Padding_Scheme, which is used in
+ * OEMCrypto_GenerateRSASignature(). The value of allowed_schemes must also be
+ * wrapped with RSA key. We recommend storing the magic string "SIGN" with
+ * the key to distinguish keys that have a value for allowed_schemes from
+ * those that should use the default allowed_schemes. Devices that do not
+ * support the alternative signing algorithms may refuse to load these keys
+ * and return an error of OEMCrypto_ERROR_NOT_IMPLEMENTED. The main use case
+ * for these alternative signing algorithms is to support devices that use
+ * X509 certificates for authentication when acting as a ChromeCast receiver.
+ * This is not needed for devices that wish to send data to a ChromeCast.
+ *
+ * If the first four bytes of the buffer `enc_private_key` are not the string
+ * "SIGN", then this key may not be used with OEMCrypto_GenerateRSASignature().
+ *
+ * Verification and Algorithm:
+ * The following checks should be performed. If any check fails, an error is
+ * returned, and the key is not loaded.
+ * 1. Check that all the pointer values passed into it are within the
+ * buffer specified by message and message_length.
+ * 2. Verify that (in) wrapped_private_key_length is large enough to hold
+ * the rewrapped key, returning OEMCrypto_ERROR_SHORT_BUFFER otherwise.
+ * 3. Verify the message signature, using the derived signing key
+ * (mac_key[server]) from a previous call to
+ * OEMCrypto_GenerateDerivedKeys() or OEMCrypto_DeriveKeysFromSessionKey().
+ * 4. The function ODK_ParseProvisioning is called to parse the message.
+ * 5. Decrypt enc_private_key in the buffer private_key using the session's
+ * derived encryption key (enc_key). Use enc_private_key_iv as the initial
+ * vector for AES_128-CBC mode, with PKCS#5 padding. The private_key should
+ * be kept in secure memory and protected from the user.
+ * 6. If the first four bytes of the buffer private_key are the string "SIGN",
+ * then the actual RSA key begins on the 9th byte of the buffer. The
+ * second four bytes of the buffer is the 32 bit field
+ * "allowed_schemes", of type RSA_Padding_Scheme, which is used in
+ * OEMCrypto_GenerateRSASignature(). The value of allowed_schemes must
+ * also be wrapped with RSA key. We recommend storing the magic string
+ * "SIGN" with the key to distinguish keys that have a value for
+ * allowed_schemes from those that should use the default
+ * allowed_schemes. Devices that do not support the alternative signing
+ * algorithms may refuse to load these keys and return an error of
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED. The main use case for these
+ * alternative signing algorithms is to support devices that use X.509
+ * certificates for authentication when acting as a ChromeCast receiver.
+ * This is not needed for devices that wish to send data to a ChromeCast.
+ * 7. If the first four bytes of the buffer private_key are not the string
+ * "SIGN", this key may not be used with OEMCrypto_GenerateRSASignature().
+ * 8. After possibly skipping past the first 8 bytes signifying the allowed
+ * signing algorithm, the rest of the buffer private_key contains an ECC
+ * private key or an RSA private key in PKCS#8 binary DER encoded
+ * format. The OEMCrypto library shall verify that this private key is
+ * valid.
+ * 9. Re-encrypt the device private key with an internal key (such as one
+ * derived by the OEM key or Widevine Keybox key) and the generated IV
+ * using AES-128-CBC with PKCS#5 padding. The data should also be
+ * signed. This algorithm is just a suggestion. The implementer may use any
+ * suitable encrypting and validation algorithm with a key that ties it to
+ * the device.
+ * 10. Copy the rewrapped key to the buffer specified by wrapped_private_key
+ * and the size of the wrapped key to wrapped_private_key_length.
+ *
+ * @param[in] session: crypto session identifier.
+ * @param[in] message: pointer to memory containing data.
+ * @param[in] message_length: length of the message, in bytes.
+ * @param[in] core_message_length: length of the core submessage, in bytes.
+ * @param[in] signature: pointer to memory containing the signature.
+ * @param[in] signature_length: length of the signature, in bytes.
+ * @param[out] wrapped_private_key: pointer to buffer in which encrypted RSA or
+ * ECC private key should be stored. May be null on the first call in order
+ * to find required buffer size.
+ * @param[in,out] wrapped_private_key_length: (in) length of the encrypted
+ * private key, in bytes. (out) actual length of the encrypted private key
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_KEY
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
+ * @retval OEMCrypto_ERROR_INVALID_NONCE
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_LoadProvisioning(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ size_t core_message_length, const uint8_t* signature,
+ size_t signature_length, uint8_t* wrapped_private_key,
+ size_t* wrapped_private_key_length);
+
+/**
+ * Loads a wrapped RSA or ECC private key to secure memory for use by this
+ * session in future calls to OEMCrypto_PrepAndSignLicenseRequest() or
+ * OEMCrypto_DeriveKeysFromSessionKey(). The wrapped private key will be the
+ * one verified and wrapped by OEMCrypto_LoadProvisioning(). The private key
+ * should be stored in secure memory.
+ *
+ * If the bit field "allowed_schemes" was wrapped with this RSA key, its
+ * value will be loaded and stored with the RSA key, and the key may be used
+ * with calls to OEMCrypto_GenerateRSASignature(). If there was not a bit field
+ * wrapped with the RSA key, the key will be used for
+ * OEMCrypto_PrepAndSignLicenseRequest() or OEMCrypto_DeriveKeysFromSessionKey()
+ *
+ * @verification
+ * The following checks should be performed. If any check fails, an error is
+ * returned, and the RSA key is not loaded.
+ * 1. The wrapped key has a valid signature, as described in
+ * OEMCrypto_LoadProvisioning().
+ * 2. The decrypted key is a valid private RSA key.
+ * 3. If a value for allowed_schemes is included with the key, it is a
+ * valid value.
+ *
+ * @param[in] session: crypto session identifier.
+ * @param[in] key_type: indicates either an RSA or ECC key for devices that
+ * support both.
+ * @param[in] wrapped_private_key: wrapped device private key (RSA or ECC).
+ * This is the wrapped key generated by OEMCrypto_LoadProvisioning().
+ * @param[in] wrapped_private_key_length: length of the wrapped key buffer, in
+ * bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_KEY
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_LoadDRMPrivateKey(OEMCrypto_SESSION session,
+ OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key,
+ size_t wrapped_private_key_length);
+
+/**
+ * Some platforms do not support keyboxes or OEM Certificates. On those
+ * platforms, there is a DRM certificate baked into the OEMCrypto library.
+ * This is unusual, and is only available for L3 devices. In order to debug
+ * and test those devices, they should be able to switch to the test DRM
+ * certificate.
+ *
+ * Temporarily use the standard test RSA key until the next call to
+ * OEMCrypto_Terminate(). This allows a standard suite of unit tests to be run
+ * on a production device without permanently changing the key. Using the
+ * test key is not persistent.
+ *
+ * The test key can be found in the OEMCrypto unit test, in PKCS8 form as the
+ * constant kTestRSAPKCS8PrivateKeyInfo2_2048.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED devices that use a keybox should
+ * not implement this function
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 10.
+ */
+OEMCryptoResult OEMCrypto_LoadTestRSAKey(void);
+
+/**
+ * The OEMCrypto_GenerateRSASignature() method is only used for devices that are
+ * CAST receivers. This function is called after OEMCrypto_LoadDRMPrivateKey()
+ * for the same session.
+ *
+ * The parameter padding_scheme has two possible legacy values:
+ *
+ * 0x1 - RSASSA-PSS with SHA1.
+ *
+ * 0x2 - PKCS1 with block type 1 padding (only).
+ *
+ * The only supported padding scheme is 0x2 since version 16 of this API. In
+ * this second case, the "message" is already a digest, so no further hashing
+ * is applied, and the message_length can be no longer than 83 bytes. If the
+ * message_length is greater than 83 bytes OEMCrypto_ERROR_SIGNATURE_FAILURE
+ * shall be returned.
+ *
+ * The second padding scheme is for devices that use X509 certificates for
+ * authentication. The main example is devices that work as a Cast receiver,
+ * like a ChromeCast, not for devices that wish to send to the Cast device,
+ * such as almost all Android devices. OEMs that do not support X509
+ * certificate authentication need not implement this function and can return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @verification
+ * Both the padding_scheme and the RSA key's allowed_schemes must be 0x2. If
+ * not, then the signature is not computed and the error
+ * OEMCrypto_ERROR_INVALID_KEY is returned.
+ *
+ * @param[in] session: crypto session identifier.
+ * @param[in] message: pointer to memory containing message to be signed.
+ * @param[in] message_length: length of the message, in bytes.
+ * @param[out] signature: buffer to hold the message signature. On return, it
+ * will contain the message signature generated with the device private RSA
+ * key using RSASSA-PSS. Will be null on the first call in order to find
+ * required buffer size.
+ * @param[in,out] signature_length: (in) length of the signature buffer, in
+ * bytes. (out) actual length of the signature
+ * @param[in] padding_scheme: specify which scheme to use for the signature.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if the signature buffer is too small.
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_INVALID_KEY
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED if algorithm > 0, and the device
+ * does not support that algorithm.
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_GenerateRSASignature(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ uint8_t* signature, size_t* signature_length,
+ RSA_Padding_Scheme padding_scheme);
+
+/**
+ * OEMCrypto will use ODK_PrepareCoreProvisioningRequest() or
+ * ODK_PrepareCoreProvisioning40Request(), as described in the document
+ * "Widevine Core Message Serialization", to prepare the core message.
+ * ODK_PrepareCoreProvisioningRequest() for Provisioning 2 or 3, and
+ * ODK_PrepareCoreProvisioning40Request() for Provisioning 4. If the ODK
+ * function returns an error, the error should be returned by OEMCrypto to the
+ * CDM layer. If it returns OEMCrypto_SUCCESS, then OEMCrypto shall compute the
+ * signature of the entire message. The entire message is the buffer starting at
+ * message with length message_length.
+ *
+ * For a device that has a keybox, i.e. Provisioning 2.0, OEMCrypto will sign
+ * the request with the session's derived client mac key from the previous
+ * call to OEMCrypto_GenerateDerivedKeys().
+ *
+ * For Provisioning 3.0, i.e. a device that has a baked in OEM Certificate,
+ * OEMCrypto will sign the request with the private key associated with the OEM
+ * Certificate. The key shall have been loaded by a previous call to
+ * OEMCrypto_LoadDRMPrivateKey().
+ *
+ * For Provisioning 4.0, i.e. a device that uses a Boot Chain Certificate to
+ * request and OEM cert, a request for an OEM cert is signed by the OEM private
+ * key. A request for a DRM cert is signed by the DRM private key. The DRM cert
+ * that was generated on the device in OEMCrypto_GenerateCertificateKeyPair() is
+ * signed by the OEM cert private key.
+ *
+ * Refer to the Signing Messages Sent to a Server section above for more
+ * details.
+ *
+ * NOTE: if signature pointer is null and/or input signature_length is zero,
+ * this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
+ * signature_length to the size needed to receive the output signature.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in,out] message: Pointer to memory for the entire message. Modified by
+ * OEMCrypto via the ODK library.
+ * @param[in] message_length: length of the entire message buffer.
+ * @param[in,out] core_message_size: length of the core message at the beginning
+ * of the message. (in) size of buffer reserved for the core message, in
+ * bytes. (out) actual length of the core message, in bytes.
+ * @param[out] signature: pointer to memory to receive the computed signature.
+ * @param[in,out] signature_length: (in) length of the signature buffer, in
+ * bytes. (out) actual length of the signature, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if signature buffer is not large enough
+ * to hold the signature.
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support message sizes as described in the section
+ * OEMCrypto_ResourceRatingTier().
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_PrepAndSignProvisioningRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_size, uint8_t* signature, size_t* signature_length);
+
+/// @}
+
+/// @addtogroup usage_table
+/// @{
+
+/**
+ * This creates a new Usage Table Header with no entries. If there is already
+ * a generation number stored in secure storage, it will be incremented by 1
+ * and used as the new Master Generation Number. This will only be called if
+ * the CDM layer finds no existing usage table on the file system. OEMCrypto
+ * will encrypt and sign the new, empty, header and return it in the provided
+ * buffer.
+ *
+ * The new entry should be created with a status of kUnused and all times
+ * times should be set to 0.
+ *
+ * Devices that do not implement a Session Usage Table may return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @param[out] header_buffer: pointer to memory where encrypted usage table
+ * header is written.
+ * @param[in,out] header_buffer_length: (in) length of the header_buffer, in
+ * bytes. (out) actual length of the header_buffer
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if header_buffer_length is too small
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE if any active entries are currently
+ * loaded
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 13.
+ */
+OEMCryptoResult OEMCrypto_CreateUsageTableHeader(uint8_t* header_buffer,
+ size_t* header_buffer_length);
+
+/**
+ * This loads the Usage Table Header. The buffer's signature is verified and
+ * the buffer is decrypted. OEMCrypto will verify the verification string. If
+ * the Master Generation Number is more than 1 off, the table is considered
+ * bad, the headers are NOT loaded, and the error
+ * OEMCrypto_ERROR_GENERATION_SKEW is returned. If the generation number is
+ * off by 1, the warning OEMCrypto_WARNING_GENERATION_SKEW is returned but
+ * the header is still loaded. This warning may be logged by the CDM layer.
+ *
+ * @param[in] buffer: pointer to memory containing encrypted usage table header.
+ * @param[in] buffer_length: length of the buffer, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED some devices do not implement usage
+ * tables.
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_WARNING_GENERATION_SKEW if the generation number is off
+ * by exactly 1.
+ * @retval OEMCrypto_ERROR_GENERATION_SKEW if the generation number is off by
+ * more than 1.
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE if the signature failed.
+ * @retval OEMCrypto_ERROR_BAD_MAGIC verification string does not match.
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_LoadUsageTableHeader(const uint8_t* buffer,
+ size_t buffer_length);
+
+/**
+ * This creates a new usage entry. The size of the header will be increased
+ * by 8 bytes, and secure volatile memory will be allocated for it. The new
+ * entry will be associated with the given session. The status of the new
+ * entry will be set to "unused". OEMCrypto will set *usage_entry_number to
+ * be the index of the new entry. The first entry created will have index 0.
+ * The new entry will be initialized with a generation number equal to the
+ * master generation number, which will also be stored in the header's new
+ * slot. Then the master generation number will be incremented. Since each
+ * entry's generation number is less than the master generation number, the
+ * new entry will have a generation number that is larger than all other
+ * entries and larger than all previously deleted entries. This helps prevent
+ * a rogue application from deleting an entry and then loading an old version
+ * of it.
+ *
+ * If the session already has a usage entry associated with it, the error
+ * OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES is returned. It is an error to attempt
+ * to create or load a second usage entry into a session that already has a
+ * usage entry.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[out] usage_entry_number: index of new usage entry.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED some devices do not implement usage
+ * tables.
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES if there is no room in
+ * memory to increase the size of the usage table header. The CDM layer
+ * can delete some entries and then try again, or it can pass the error
+ * up to the application.
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES if there already is a usage
+ * entry loaded into this session
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 13.
+ */
+OEMCryptoResult OEMCrypto_CreateNewUsageEntry(OEMCrypto_SESSION session,
+ uint32_t* usage_entry_number);
+
+/**
+ * This allows a session to take an existing usage entry. The effect of this
+ * call is identical to that of creating an entry via
+ * OEMCrypto_CreateUsageEntry(), except that the usage table header does not
+ * change size. All information related to the previous entry should be cleared
+ * from the header. The new entry will be initialized with a generation number
+ * equal to the master generation number, which will also be stored in the
+ * header’s existing slot. Then the master generation number will be
+ * incremented.
+ *
+ * If the session already has a usage entry associated with it, the error
+ * OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES is returned.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] usage_entry_number: index of new usage entry.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED some devices do not implement usage
+ * tables.
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES if there already is a usage
+ * entry loaded into this session
+ * @retval OEMCrypto_ERROR_INVALID_SESSION when entry number is in use by
+ * another session
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 17.
+ */
+OEMCryptoResult OEMCrypto_ReuseUsageEntry(OEMCrypto_SESSION session,
+ uint32_t usage_entry_number);
+
+/**
+ * This loads a usage entry saved previously by UpdateUsageEntry. The
+ * signature at the beginning of the buffer is verified and the buffer will
+ * be decrypted. Then the verification field in the entry will be verified.
+ * The index in the entry must match the index passed in. The generation
+ * number in the entry will be compared against the entry's corresponding
+ * generation number in the header. If it is off by 1, a warning is returned,
+ * but the entry is still loaded. This warning may be logged by the CDM
+ * layer. If the generation number is off by more than 1, an error is
+ * returned and the entry is not loaded.
+ *
+ * OEMCrypto shall call ODK_ReloadClockValues, as described in "License
+ * Duration and Renewal" to set the session's clock values.
+ *
+ * If the entry is already loaded into another open session, then this fails and
+ * returns OEMCrypto_ERROR_INVALID_SESSION. If the session already has a usage
+ * entry associated with it, the error OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES is
+ * returned. It is also an error to try to reload the same usage entry into the
+ * same open session twice.
+ *
+ * Before version API 16, the usage entry stored the time that the license
+ * was loaded. This value is now interpreted as the time that the licence
+ * request was signed. This can be achieved by simply renaming the field and
+ * using the same value when reloading an older entry.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] usage_entry_number: index of existing usage entry.
+ * @param[in] buffer: pointer to memory containing encrypted usage table entry.
+ * @param[in] buffer_length: length of the buffer, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED some devices do not implement usage
+ * tables.
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE index beyond end of table.
+ * @retval OEMCrypto_ERROR_INVALID_SESSION entry associated with another
+ * session or the index is wrong.
+ * @retval OEMCrypto_WARNING_GENERATION_SKEW if the generation number is off
+ * by exactly 1.
+ * @retval OEMCrypto_ERROR_GENERATION_SKEW if the generation number is off by
+ * more than 1.
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE if the signature failed.
+ * @retval OEMCrypto_ERROR_BAD_MAGIC verification string does not match.
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES if there already is a usage
+ * entry loaded into this session
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 13.
+ */
+OEMCryptoResult OEMCrypto_LoadUsageEntry(OEMCrypto_SESSION session,
+ uint32_t usage_entry_number,
+ const uint8_t* buffer,
+ size_t buffer_length);
+
+/**
+ * Updates the session's usage entry and fills buffers with the encrypted and
+ * signed entry and usage table header.
+ *
+ * OEMCrypto shall call ODK_UpdateLastPlaybackTime to update the session's
+ * clock values, as discussed in the document "License Duration and Renewal".
+ * The values in the session's clock values structure are copied to the usage
+ * entry.
+ *
+ * OEMCrypto shall update all time and status values in the entry, and then
+ * increment the entry's generation number. The corresponding generation
+ * number in the usage table header is also incremented so that it matches
+ * the one in the entry. The master generation number in the usage table
+ * header is incremented and the master generation number is copied to secure
+ * persistent storage. OEMCrypto will encrypt and sign the entry into the
+ * entry_buffer, and it will encrypt and sign the usage table header into the
+ * header_buffer. Some actions, such as the first decrypt and deactivating an
+ * entry, will also increment the entry's generation number as well as
+ * changing the entry's status and time fields. The first decryption will
+ * change the status from Inactive to Active, and it will set the time stamp
+ * "first decrypt".
+ *
+ * If the usage entry has the flag ForbidReport set, then the flag is
+ * cleared. It is the responsibility of the CDM layer to call this function and
+ * save the usage table before the next call to OEMCrypto_ReportUsage() and
+ * before the CDM is terminated. Failure to do so will result in generation
+ * number skew, which will invalidate all of the usage table.
+ *
+ * If either entry_buffer_length or header_buffer_length is not large enough,
+ * they are set to the needed size, and return OEMCrypto_ERROR_SHORT_BUFFER.
+ * In this case, the entry is not updated, ForbidReport is not cleared,
+ * generation numbers are not incremented, and no other work is done.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[out] header_buffer: pointer to memory where encrypted usage table
+ * header is written.
+ * @param[in,out] header_buffer_length: (in) length of the header_buffer, in
+ * bytes. (out) actual length of the header_buffer
+ * @param[out] entry_buffer: pointer to memory where encrypted usage table entry
+ * is written.
+ * @param[in,out] entry_buffer_length: (in) length of the entry_buffer, in
+ * bytes. (out) actual length of the entry_buffer
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED some devices do not implement usage
+ * tables.
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_UpdateUsageEntry(
+ OEMCrypto_SESSION session, OEMCrypto_SharedMemory* header_buffer,
+ size_t* header_buffer_length, OEMCrypto_SharedMemory* entry_buffer,
+ size_t* entry_buffer_length);
+
+/**
+ * This deactivates the usage entry associated with the current session. This
+ * means that the status of the usage entry is changed to InactiveUsed if it
+ * was Active, or InactiveUnused if it was Unused. This also increments the
+ * entry's generation number, and the header's master generation number. The
+ * corresponding generation number in the usage table header is also
+ * incremented so that it matches the one in the entry. The entry's flag
+ * ForbidReport will be set. This flag prevents an application from
+ * generating a report of a deactivated license without first saving the
+ * entry.
+ *
+ * OEMCrypto shall call ODK_DeactivateUsageEntry to update the session's
+ * clock values, as discussed in the document "License Duration and Renewal".
+ *
+ * It is allowed to call this function multiple times. If the state is
+ * already InactiveUsed or InactiveUnused, then this function does not change
+ * the entry or its state.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] pst: pointer to memory containing Provider Session Token.
+ * @param[in] pst_length: length of the pst, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT an entry was not created or loaded,
+ * or the pst does not match.
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support pst sizes of at least 255 bytes.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 16.
+ */
+OEMCryptoResult OEMCrypto_DeactivateUsageEntry(OEMCrypto_SESSION session,
+ const uint8_t* pst,
+ size_t pst_length);
+
+/**
+ * All fields of OEMCrypto_PST_Report are in network byte order.
+ *
+ * If the buffer_length is not sufficient to hold a report structure, set
+ * buffer_length and return OEMCrypto_ERROR_SHORT_BUFFER.
+ *
+ * If an entry was not loaded or created with OEMCrypto_CreateNewUsageEntry() or
+ * OEMCrypto_LoadUsageEntry() return the error
+ * OEMCrypto_ERROR_INVALID_CONTEXT. If the pst does not match that in the entry,
+ * return OEMCrypto_ERROR_WRONG_PST.
+ *
+ * If the usage entry's flag ForbidReport is set, indicating the entry has
+ * not been saved since the entry was deactivated, then the error
+ * OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE is returned and a report is not
+ * generated. Similarly, if any key in the session has been used since the
+ * last call to OEMCrypto_UpdateUsageEntry(), then the report is not generated,
+ * and OEMCrypto returns the error OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE.
+ *
+ * The pst_report is filled out by subtracting the times in the Usage Entry
+ * from the current time on the secure clock. This design was chosen to avoid
+ * a requirement to sync the device's secure clock with any external clock.
+ *
+ * 
+ *
+ * Valid values for status are:
+ *
+ * - 0 = kUnused -- the keys have not been used to decrypt.
+ * - 1 = kActive -- the keys have been used, and have not been deactivated.
+ * - 2 = kInactive - deprecated. Use kInactiveUsed or kInactiveUnused.
+ * - 3 = kInactiveUsed -- the keys have been marked inactive after being
+ * active.
+ * - 4 = kInactiveUnused -- they keys have been marked inactive, but were
+ * never active.
+ * The clock_security_level is reported as follows:
+ *
+ * - 0 = Insecure Clock - clock just uses system time.
+ * - 1 = Secure Timer - clock runs from a secure timer which is initialized
+ * from system time when OEMCrypto becomes active and cannot be modified
+ * by user software or the user while OEMCrypto is active. A secure
+ * timer cannot run backwards, even while OEMCrypto is not active.
+ * - 2 = Secure Clock - Real-time clock set from a secure source that
+ * cannot be modified by user software regardless of whether OEMCrypto
+ * is active or inactive. The clock time can only be modified by
+ * tampering with the security software or hardware.
+ * - 3 = Hardware Secure Clock - Real-time clock set from a secure source
+ * that cannot be modified by user software and there are security
+ * features that prevent the user from modifying the clock in hardware,
+ * such as a tamper proof battery.
+ *
+ * 
+ *
+ * After pst_report has been filled in, the HMAC SHA1 signature is computed
+ * for the buffer from bytes 20 to the end of the pst field. The signature is
+ * computed using the mac_key[client] which is stored in the usage table. The
+ * HMAC SHA1 signature is used to prevent a rogue application from using
+ * OMECrypto_GenerateSignature to forge a Usage Report.
+ *
+ * Before version 16 of this API, seconds_since_license_received was reported
+ * instead of seconds_since_license_signed. For any practical bookkeeping
+ * purposes, these events are essentially at the same time.
+ *
+ * Devices that do not implement a Session Usage Table may return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] pst: pointer to memory containing Provider Session Token.
+ * @param[in] pst_length: length of the pst, in bytes.
+ * @param[out] buffer: pointer to buffer in which usage report should be
+ * stored. May be null on the first call in order to find required buffer
+ * size.
+ * @param[in,out] buffer_length: (in) length of the report buffer, in bytes.
+ * (out) actual length of the report
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if report buffer is not large enough
+ * to hold the output report.
+ * @retval OEMCrypto_ERROR_INVALID_SESSION no open session with that id.
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE if no call to UpdateUsageEntry
+ * since last call to Deactivate or since key use.
+ * @retval OEMCrypto_ERROR_WRONG_PST report asked for wrong pst.
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support pst sizes of at least 255 bytes.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 13.
+ */
+OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
+ const uint8_t* pst, size_t pst_length,
+ uint8_t* buffer, size_t* buffer_length);
+
+/**
+ * Moves the entry associated with the current session from one location in
+ * the usage table header to another. This function is used by the CDM layer
+ * to defragment the usage table. This does not modify any data in the entry,
+ * except the index and the generation number. The index in the session's
+ * usage entry will be changed to new_index. The generation number in
+ * session's usage entry and in the header for new_index will be increased to
+ * the master generation number, and then the master generation number is
+ * incremented. If there was an existing entry at the new location, it will
+ * be overwritten. It is an error to call this when the entry that was at
+ * new_index is associated with a currently open session. In this case, the
+ * error code OEMCrypto_ERROR_ENTRY_IN_USE is returned. It is the CDM layer's
+ * responsibility to call UpdateUsageEntry after moving an entry. It is an
+ * error for new_index to be beyond the end of the existing usage table
+ * header.
+ *
+ * Devices that do not implement a Session Usage Table may return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] new_index: new index to be used for the session's usage entry
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_ENTRY_IN_USE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 13.
+ */
+OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session,
+ uint32_t new_index);
+
+/**
+ * This shrinks the usage table and the header. This function is used by the CDM
+ * layer after it has defragmented the usage table and can delete unused
+ * entries. It is an error if any open session is associated with an entry that
+ * will be erased - the error OEMCrypto_ERROR_ENTRY_IN_USE shall be returned in
+ * this case, and the header shall not be modified. If new_entry_count is larger
+ * than the current size, then the header is not changed and the error
+ * OEMCrypto_ERROR_UNKNOWN_FAILURE is returned. If the header has not been
+ * previously loaded, then OEMCrypto_ERROR_UNKNOWN_FAILURE is returned.
+ * OEMCrypto will increment the master generation number in the header and store
+ * the new value in secure persistent storage. Then, OEMCrypto will encrypt and
+ * sign the header into the provided buffer. The generation numbers of all
+ * remaining entries will remain unchanged. The next time
+ * OEMCrypto_CreateNewUsageEntry() is called, the new entry will have an index
+ * of new_entry_count.
+ *
+ * Devices that do not implement a Session Usage Table may return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * If header_buffer_length is not large enough to hold the new table, it is
+ * set to the needed value, the generation number is not incremented, and
+ * OEMCrypto_ERROR_SHORT_BUFFER is returned.
+ *
+ * If the header has not been loaded or created, return the error
+ * OEMCrypto_ERROR_UNKNOWN_FAILURE.
+ *
+ * @param[in] new_entry_count: number of entries to be in the new header.
+ * @param[out] header_buffer: pointer to memory where encrypted usage table
+ * header is written.
+ * @param[in,out] header_buffer_length: (in) length of the header_buffer, in
+ * bytes. (out) actual length of the header_buffer
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_ENTRY_IN_USE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 13.
+ */
+OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(uint32_t new_entry_count,
+ uint8_t* header_buffer,
+ size_t* header_buffer_length);
+
+/// @}
+
+/// @addtogroup prov40
+/// @{
+
+/**
+ * Get the serialized boot certificate chain in CBOR format used in
+ * provisioning 4.
+ *
+ * @param[out] bcc: pointer to the buffer that receives the serialized boot
+ * certificate chain in CBOR format.
+ * @param[in,out] bcc_length - on input, size of the caller's bcc buffer. On
+ * output, the number of bytes written into the buffer.
+ * @param[out] additional_signature: pointer to the buffer that receives
+ * additional device key signature (certificate chain). This field is only
+ * used by the signing model where a vendor certificate is available on the
+ * device.
+ * @param[in,out] additional_signature_length - on input, size of the caller's
+ * additional_signature buffer. On output, the number of bytes written into
+ * the buffer.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if any of the buffers is too small to
+ * return the bcc or additional_signature.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED if provisioning 4 is not supported.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_GetBootCertificateChain(
+ uint8_t* bcc, size_t* bcc_length, uint8_t* additional_signature,
+ size_t* additional_signature_length);
+
+/**
+ * Generates a key pair used in OEM and DRM certificate provisioning. The public
+ * key is supposed to be certified by the server. The private key is wrapped
+ * with the encryption key so it can be stored in the file system.
+ *
+ * The |public_key_signature| output is formatted differently depending
+ * on whether or not an OEM private key has been loaded.
+ *
+ * If an OEM private key is unavailable, the request is assumed to be for OEM
+ * certificate provisioning. In this case, the public key is signed by the
+ * device private key. The format of |public_key_signature| in this case is a
+ * COSE_Sign1 CBOR array. The format is described in RFC 8152 Section 4.2 and
+ * 4.4, as well as Android IRemotelyProvisionedComponent.aidl (under
+ * "SignedData")
+ *
+ * ~~~
+ * |public_key_signature|: COSE_Sign1 CBOR array
+ * [
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 /
+ * AlgorithmES384 },
+ * unprotected: {},
+ * payload: bstr .cbor Data / nil,
+ * signature: bstr ; PureEd25519(priv_key, Sig_structure) /
+ * ; ECDSA(priv_key, Sig_structure)
+ * ]
+ * ~~~
+ *
+ * Notes:
+ * 1. The payload field in the COSE_Sign1 struct is the public key generated
+ * by OEMCrypto_GenerateCertificateKeyPair
+ * 2. The signature field in the COSE_Sign1 struct is the concatenation of the
+ * (R,S) values from the EC/Ed signature. If either R or S is smaller than
+ * the key size, it is left-padded with 0 to match the key size as
+ * described in RFC 8152. This signature is not DER encoded.
+ * 3. The signature is generated by calling the selected EC signing function
+ * (PureEd25519 or one of the supported ECDSA algorithms) on
+ * `Sig_structure`, which is a CBOR array described below. The payload
+ * field in Sig_structure is the same as the payload in the above
+ * COSE_Sign1 CBOR array.
+ *
+ * ~~~
+ * Sig_structure: CBOR array
+ * [
+ * context: "Signature1",
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 /
+ * AlgorithmES384 },
+ * external_aad: bstr .size 0,
+ * payload: bstr .cbor Data / nil,
+ * ]
+ * ~~~
+ *
+ * If an OEM private key is available, the request is assumed to be for DRM
+ * certificate provisioning and the public key is signed by the OEM private key.
+ * If the OEM private key is an RSA key, then |public_key_signature| is the raw
+ * output of the RSA sign operation with RSASSA-PSS padding. If the OEM private
+ * key is an ECC key, then |public_key_signature| is the ASN.1 DER-encoded (R,S)
+ * signature as specified in RFC 3279 2.2.3.
+ *
+ * After this function completes successfully, the session will hold a private
+ * key and will be ready for a call to
+ * OEMCrypto_PrepAndSignProvisioningRequest(). In particular, when this
+ * function is used to generate a DRM Certificate key pair, the session will be
+ * ready to sign a provisioning request with the DRM Cert private key. When this
+ * function is used to generate an OEM Certificate key pair, the session will be
+ * ready to sign a provisioning request with the OEM Cert private key.
+ *
+ * The public key shall be an ASN.1 DER-encoded SubjectPublicKeyInfo as
+ * specified in RFC 5280. Widevine recommends ECC keys for Provisioning 4.0, but
+ * an RSA key may also be used. If the key is an RSA key, then the encoding
+ * should use "rsaEncryption" (OID 1.2.840.113549.1.1.1), and not RSASSA-PSS.
+ *
+ * @param[in] session: session id.
+ * @param[out] public_key: pointer to the buffer that receives the public key
+ * that is to be certified by the server. The key must be an ASN.1
+ * DER-encoded SubjectPublicKeyInfo as specified in RFC 5280.
+ * @param[in,out] public_key_length: on input, size of the caller's public_key
+ * buffer. On output, the number of bytes written into the buffer.
+ * @param[out] public_key_signature: pointer to the buffer that receives the
+ * signature of the public key. The format depends on whether an OEM private
+ * key has been loaded.
+ * @param[in,out] public_key_signature_length: on input, size of the caller's
+ * public_key_signature buffer. On output, the number of bytes written into
+ * the buffer.
+ * @param[out] wrapped_private_key: pointer to the buffer that receives the
+ * encrypted private key. It is encrypted by the device encryption key.
+ * @param[in,out] wrapped_private_key_length: on input, size of the caller's
+ * wrapped_private_key buffer. On output, the number of bytes written into
+ * the buffer.
+ * @param[out] key_type: the type of the generated key pair (RSA or ECC).
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if any of the buffer |public_key|,
+ * |public_key_signature| or |wrapped_private_key_size| is too small.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_GenerateCertificateKeyPair(
+ OEMCrypto_SESSION session, uint8_t* public_key, size_t* public_key_length,
+ uint8_t* public_key_signature, size_t* public_key_signature_length,
+ uint8_t* wrapped_private_key, size_t* wrapped_private_key_length,
+ OEMCrypto_PrivateKeyType* key_type);
+
+/**
+ * Get the serialized device information in CBOR map format. This is for devices
+ * that use Provisioning 4.0, with the device key uploading option in the
+ * factory.
+ *
+ * The device
+ * information may contain, for example, device make and model, "fused" status,
+ * and other properties, which is intended to be 1) uploaded during device
+ * manufacture in the factory, 2) checked by the server to verify that the
+ * provisioning request is coming from the expected device in the fields, based
+ * on the values previously uploaded and registered.
+ *
+ * Devices that do not support Provisioning 4.0, or do not support
+ * Provisioning 4.0 Uploading Option should return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @param[out] device_info: pointer to the buffer that receives the serialized
+ * device information in CBOR map format.
+ * @param[in,out] device_info_length: on input, size of the caller's
+ * device_info buffer. On output, the number of bytes written into the buffer.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if device_info_length is too small to
+ * return the device_info.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED if provisioning 4 is not supported,
+ * or device information is not available on the platform.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 18.
+ */
+OEMCryptoResult OEMCrypto_GetDeviceInformation(uint8_t* device_info,
+ size_t* device_info_length);
+
+/**
+ * Get the serialized signed Certificate Signing Request (CSR) payload in
+ * COSE_Sign1 format. This is for devices that use Provisioning 4.0, with the
+ * device key uploading option in the factory.
+ *
+ * With the uploading option, the RKP factory extraction tool provided by Google
+ * makes a call to this function to collect the signed CSR payload for
+ * generating the CSR to be uploaded to the device database. The CSR payload is
+ * signed by the leaf cert of the Boot Certificate Chain.
+ *
+ * The format of a CSR payload before COSE_Sign1 is a CBOR array described in
+ * Android IRemotelyProvisionedComponent.aidl (under "CsrPayload"):
+ *
+ * ~~~
+ * CsrPayload = [ ; CBOR Array defining the payload for CSR.
+ * version: 3, ; The CsrPayload CDDL Schema version.
+ * CertificateType: "widevine" ; The type of certificate being requested.
+ * DeviceInfo, ; Defined in Android DeviceInfo.aidl
+ * KeysToSign: [] ; Empty list
+ * ]
+ * ~~~
+ *
+ * The type of CertificateType is tstr and the value should always be
+ * "widevine". The type of KeysToSign is CBOR array and the value is not used,
+ * which should be left as an empty list. Note that the DeviceInfo above is a
+ * CBOR map structure defined in DeviceInfo.aidl, which can be constructed from
+ * the input |encoded_device_info|. DeviceInfo must be canonicalized according
+ * to the specification in RFC 7049. The required fields from DeviceInfo.aidl
+ * are: brand, manufacturer, product, model, device, vb_state, bootloader_state,
+ * vbmeta_digest, security_level.
+ *
+ * Once CsrPayload is prepared, together with |challenge| it is signed by the
+ * leaf cert of BCC, in the format of:
+ *
+ * ~~~
+ * |signed_csr_payload| = SignedData<[
+ * challenge: bstr .size (0..64),
+ * bstr .cbor CsrPayload,
+ * ]>
+ * ~~~
+ *
+ * This function should output |signed_csr_payload| in the format of
+ * SignedData, which is a COSE_Sign1 CBOR and is defined in Android
+ * IRemotelyProvisionedComponent.aidl (under "SignedData"):
+ *
+ * ~~~
+ * SignedData = [
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 /
+ * AlgorithmES384 },
+ * unprotected: {},
+ * payload: bstr .cbor Data / nil,
+ * signature: bstr ; PureEd25519(priv_key, Sig_structure) /
+ * ; ECDSA(priv_key, Sig_structure)
+ * ]
+ * ~~~
+ *
+ * Also see OEMCrypto_GenerateCertificateKeyPair() for more details of
+ * SignedData and Sig_structure.
+ *
+ * Data in the payload field of SignedData is a CBOR array:
+ *
+ * ~~~
+ * Data = [
+ * challenge: bstr .size (0..64),
+ * bstr .cbor CsrPayload,
+ * ]
+ * ~~~
+ *
+ * Devices that do not support Provisioning 4.0, or do not support
+ * Provisioning 4.0 Uploading Option should return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED.
+ *
+ * @param[in] challenge: pointer to the buffer containing a byte string to be
+ * signed. It is generated by the RKP factory extraction tool.
+ * @param[in] challenge_length: size of the challenge buffer.
+ * @param[in] encoded_device_info: pointer to the buffer containing the
+ * serialized device information in CBOR map format. It should be returned as
+ * `device_info` in a call to the function `OEMCrypto_GetDeviceInformation()`.
+ * @param[in] encoded_device_info_length: size of the encoded_device_info
+ * buffer.
+ * @param[out] signed_csr_payload: pointer to the buffer that receives the
+ * serialized signed CSR payload in COSE_Sign1 format.
+ * @param[in,out] signed_csr_payload_length: on input, size of the caller's
+ * signed_csr_payload buffer. On output, the number of bytes written into the
+ * buffer.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT if challenge_length or
+ * encoded_device_info_length is 0, or any pointer is NULL
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if signed_csr_payload_length is too
+ * small to return the signed_csr_payload.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED if provisioning 4 is not supported,
+ * or device information is not available on the platform.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 18.
+ */
+OEMCryptoResult OEMCrypto_GetDeviceSignedCsrPayload(
+ const uint8_t* challenge, size_t challenge_length,
+ const uint8_t* encoded_device_info, size_t encoded_device_info_length,
+ uint8_t* signed_csr_payload, size_t* signed_csr_payload_length);
+
+/**
+ * Loads an OEM private key to a session. The key will be used in signing DRM
+ * certificate request, or the public key generated by calling
+ * OEMCrypto_GenerateCertificateKeyPair.
+ *
+ * @param[in] session: session id.
+ * @param[in] key_type: type of the leaf key (RSA or ECC).
+ * @param[in] wrapped_private_key: the encrypted private key. This is the
+ * wrapped key generated by OEMCrypto_GenerateCertificateKeyPair.
+ * @param[in] wrapped_private_key_length: length of |wrapped_private_key| in
+ * bytes.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_KEY
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 17.
+ */
+OEMCryptoResult OEMCrypto_InstallOemPrivateKey(
+ OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key, size_t wrapped_private_key_length);
+/// @}
+
+/// @addtogroup test_verify
+/// @{
+
+/**
+ * Enter Test Mode. This enables OEMCrypto test functionality. Without a call to
+ * this function, none of the test functions](./test-verify) shall be
+ * enabled. After this function has been called, OEMCrypto will not use the
+ * production keybox. Once OEMCrypto has entered Test Mode, it will not leave
+ * Test Mode until the next reboot.
+ *
+ * If the device is not in Test Mode, it will be in Production Mode and
+ * OEMCrypto will use a production root of trust (keybox or OEM Certificate) if
+ * available. In Production Mode, none of the test functions are enabled.
+ *
+ * Widevine recommends shipping a Production Only version of OEMCrypto on
+ * released devices. A Production Only version of OEMCrypto will have all test
+ * functions disabled. In this case, OEMCrypto_EnterTestMode() will return
+ * OEMCRYPTO_ERROR_NOT_IMPLEMENTED.
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED OEMCrypto is a production build, and
+ * does not support debug or test-only functions.
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be
+ * called simultaneously with any other function, as if the CDM holds a write
+ * lock on the OEMCrypto system. It is called once after
+ * OEMCrypto_Initialize(), and before any other test-only functions are
+ * called.
+ *
+ * @version
+ * This method is new in API version 18.
+ */
+OEMCryptoResult OEMCrypto_EnterTestMode(void);
+
+/**
+ * Returns the type of hash function supported for Full Decrypt Path Testing.
+ * A hash type of OEMCrypto_Hash_Not_Supported = 0 means this feature is not
+ * supported. OEMCrypto is not required by Google to support this feature,
+ * but support will greatly improve automated testing. A hash type of
+ * OEMCrypto_CRC_Clear_Buffer = 1 means the device will be able to compute
+ * the CRC 32 checksum of the decrypted content in the secure buffer after a
+ * call to OEMCrypto_DecryptCENC(). Google intends to provide test applications
+ * on some platforms, such as Android, that will automate decryption testing
+ * using the CRC 32 checksum of all frames in some test content.
+ *
+ * If an SOC vendor cannot support CRC 32 checksums of decrypted output, but
+ * can support some other hash or checksum, then the function should return
+ * OEMCrypto_Partner_Defined_Hash = 2 and those partners should modify the
+ * test application to compute the appropriate hash. An application that
+ * computes the CRC 32 hashes of test content and builds a hash file in the
+ * correct format will be provided by Widevine. The source of this
+ * application will be provided so that partners may modify it to compute
+ * their own hash format and generate their own hashes.
+ *
+ * @retval OEMCrypto_Hash_Not_Supported = 0;
+ * @retval OEMCrypto_CRC_Clear_Buffer = 1;
+ * @retval OEMCrypto_Partner_Defined_Hash = 2;
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method is new in API version 15.
+ */
+uint32_t OEMCrypto_SupportsDecryptHash(void);
+
+/**
+ * Set the hash value for the next frame to be decrypted. This function is
+ * called before the first subsample is passed to OEMCrypto_DecryptCENC(), when
+ * the subsample_flag has the bit OEMCrypto_FirstSubsample set. The hash is
+ * over all of the frame or sample: encrypted and clear subsamples
+ * concatenated together, up to, and including the subsample with the
+ * subsample_flag having the bit OEMCrypto_LastSubsample set. If hashing the
+ * output is not supported, then this will return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED. If the hash is ill formed or there are
+ * other error conditions, this returns OEMCrypto_ERROR_UNKNOWN_FAILURE. The
+ * length of the hash will be at most 128 bytes, and will be 4 bytes (32
+ * bits) for the default CRC32 hash.
+ *
+ * This may be called before the first call to OEMCrypto_GetKeyHandle. In that
+ * case, this function cannot verify that the key control block allows hash
+ * verification. The function DecryptCENC should verify that the key control bit
+ * allows hash verification when it is called. If an attempt is made to compute
+ * a hash when the selected key does not have the bit Allow_Hash_Verification
+ * set, then a hash should not be computed, and OEMCrypto_GetHashErrorCode()
+ * should return the error OEMCrypto_ERROR_UNKNOWN_FAILURE.
+ *
+ * OEMCrypto should compute the hash of the frame and then compare it with
+ * the correct value. If the values differ, then OEMCrypto should latch in an
+ * error and save the frame number of the bad hash. It is allowed for
+ * OEMCrypto to postpone computation of the hash until the frame is
+ * displayed. This might happen if the actual decryption operation is carried
+ * out by a later step in the video pipeline, or if you are using a partner
+ * specified hash of the decoded frame. For this reason, an error state must
+ * be saved until the call to OEMCrypto_GetHashErrorCode() is made.
+ *
+ * @param[in] session: session id for current decrypt operation
+ * @param[in] frame_number: frame number for the recent DecryptCENC sample.
+ * @param[in] hash: hash or CRC of previously decrypted frame.
+ * @param[in] hash_length: length of hash, in bytes.
+ *
+ * @retval OEMCrypto_SUCCESS if the hash was set
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED function not implemented
+ * @retval OEMCrypto_ERROR_INVALID_SESSION session not open
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER hash_length too short for supported
+ * hash type
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE hash_length too long for supported
+ * hash type
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE other error
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 15.
+ */
+OEMCryptoResult OEMCrypto_SetDecryptHash(OEMCrypto_SESSION session,
+ uint32_t frame_number,
+ const uint8_t* hash,
+ size_t hash_length);
+
+/**
+ * If the hash set in OEMCrypto_SetDecryptHash() did not match the computed
+ * hash, then an error code was saved internally. This function returns that
+ * error and the frame number of the bad hash. This will be called
+ * periodically, but might not be in sync with the decrypt loop. OEMCrypto
+ * shall not reset the error state to "no error" once any frame has failed
+ * verification. It should be initialized to "no error" when the session is
+ * first opened. If there is more than one bad frame, it is the implementer's
+ * choice if it is more useful to return the number of the first bad frame,
+ * or the most recent bad frame.
+ *
+ * If the hash could not be computed -- either because the
+ * Allow_Hash_Verification was not set in the key control block, or because
+ * there were other issues -- this function should return
+ * OEMCrypto_ERROR_UNKNOWN_FAILURE.
+ *
+ * @param[in] session: session id for operation.
+ * @param[out] failed_frame_number: frame number for sample with incorrect hash.
+ *
+ * @retval OEMCrypto_SUCCESS if all frames have had a correct hash
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_BAD_HASH if any frame had an incorrect hash
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE if the hash could not be computed
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 15.
+ */
+OEMCryptoResult OEMCrypto_GetHashErrorCode(OEMCrypto_SESSION session,
+ uint32_t* failed_frame_number);
+
+/**
+ * Allocates a secure buffer and fills out the destination buffer information
+ * in output_descriptor. The integer secure_fd may also be set to indicate
+ * the source of the buffer. OEMCrypto may use the secure_fd to help track
+ * the buffer if it wishes. The unit tests will pass a pointer to the same
+ * destination buffer description and the same secure_fd to
+ * OEMCrypto_FreeSecureBuffer when the buffer is to be freed.
+ *
+ * This is especially helpful if the hash functions above are supported. This
+ * will only be used by the OEMCrypto unit tests, so we recommend returning
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED for production devices if performance is
+ * an issue. If OEMCrypto_ERROR_NOT_IMPLEMENTED is returned, then secure
+ * buffer unit tests will be skipped.
+ *
+ * @param[in] session: session id for operation.
+ * @param[in] buffer_size: the requested buffer size.
+ * @param[out] output_descriptor: the buffer descriptor for the created
+ * buffer. This will be passed into the OEMCrypto_DecryptCENC() function.
+ * @param[out] secure_fd: a pointer to platform dependent file or buffer
+ * descriptor. This will be passed to OEMCrypto_FreeSecureBuffer().
+ *
+ * @retval OEMCrypto_SUCCESS if the buffer was created
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_OUTPUT_TOO_LARGE
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 16.
+ */
+OEMCryptoResult OEMCrypto_AllocateSecureBuffer(
+ OEMCrypto_SESSION session, size_t buffer_size,
+ OEMCrypto_DestBufferDesc* output_descriptor, int* secure_fd);
+
+/**
+ * Frees a secure buffer that had previously been created with
+ * OEMCrypto_AllocateSecureBuffer(). Any return value except OEMCrypto_SUCCESS
+ * will cause the unit test using secure buffers to fail.
+ *
+ * @param[in] session: session id for operation.
+ * @param[in,out] output_descriptor: the buffer descriptor modified by
+ * OEMCrypto_AllocateSecureBuffer()
+ * @param[in] secure_fd: The integer returned by
+ * OEMCrypto_AllocateSecureBuffer()
+ *
+ * @retval OEMCrypto_SUCCESS if the buffer was freed
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ *
+ * @threading
+ * This is a "Session Function" and may be called simultaneously with session
+ * functions for other sessions but not simultaneously with other functions
+ * for this session. It will not be called simultaneously with initialization
+ * or usage table functions. It is as if the CDM holds a write lock for this
+ * session, and a read lock on the OEMCrypto system.
+ *
+ * @version
+ * This method is new in API version 16.
+ */
+OEMCryptoResult OEMCrypto_FreeSecureBuffer(
+ OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor,
+ int secure_fd);
+
+/// @}
+
+/*
+ * OEMCrypto_OPK_SerializationVersion
+ *
+ * Note: This is an undocumented function. It is only required and used by the
+ * OPK implementation of OEMCrypto. It is not in a documentation group and does
+ * not show up on the devsite documentation page.
+ *
+ * Check the serialization protocol version used by the OEMCrypto Porting Kit
+ * (OPK). If the OPK is not used, this function must return
+ * OEMCrypto_ERROR_NOT_IMPLEMENTED. The serialization version is expressed as
+ * |major.minor|, where |major| and |minor| are integers. The TEE and REE
+ * serialization versions must match in order for OEMCrypto to communicate
+ * with the TEE. If the serialization versions do not match, calls to other
+ * OEMCrypto functions will return OPK_ERROR_INCOMPATIBLE_VERSION. A match is
+ * achieved if the |major| fields of the TEE and REE versions are the
+ * same. Differences in only the |minor| fields indicates that the protocols
+ * are different but are still compatible.
+ *
+ * @param[in,out] ree_major: pointer to memory to recieve the REE's |major|
+ * version. On input, *ree_major may be zero to request the serialization
+ * version of the REE. If *ree_major is non-zero, this function will test the
+ * TEE's compatibility using the specified REE major version.
+ * @param[in,out] ree_minor: pointer to memory to recieve the REE's |minor|
+ * version. On input, *ree_minor may be zero to request the serialization
+ * version of the REE. If *ree_minor is non-zero, this function will test the
+ * TEE's compatibility using the specified REE minor version.
+ * @param[out] tee_major: pointer to memory to recieve the TEE's |major| version
+ * @param[out] tee_minor: pointer to memory to recieve the TEE's |minor| version
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OPK_ERROR_INCOMPATIBLE_VERSION
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ */
+OEMCryptoResult OEMCrypto_OPK_SerializationVersion(uint32_t* ree_major,
+ uint32_t* ree_minor,
+ uint32_t* tee_major,
+ uint32_t* tee_minor);
+
+/****************************************************************************/
+/****************************************************************************/
+/* The following functions are optional. They are only used if the device
+ * supports OTA keybox provisioning. Widevine does not allow all devices to
+ * support OTA provisioning. Using an OTA provisioned keybox usually lowers a
+ * device's security profile in the DCSL. Please work with your Widevine Partner
+ * Engineer before implementing these functions to make sure you understand the
+ * security implications of using Keybox OTA Provisioning.
+ */
+
+/**
+ * Generate an OTA Keybox provisioning request. The format of the
+ * message is specified in the document Keybox OTA Reprovisioning. If
+ * use_test_key is true, then the debug model key and id should be
+ * used. Widevine does not allow all devices to support OTA
+ * provisioning. Using an OTA provisioned keybox usually lowers a device's
+ * security profile in the DCSL.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[out] buffer: where the provisioning request is stored.
+ * @param[in,out] buffer_length: length of the request, in bytes.
+ * @param[in] use_test_key: If non-zero, use the debug model key. This is used
+ * for testing the workflow.
+ *
+ * @retval OEMCrypto_SUCCESS on success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if buffer_length is too small.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * Any other error will be logged.
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock on
+ * the OEMCrypto system. It will be called only after
+ * OEMCrypto_IsKeyboxOrOEMCertValid() returns
+ * OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING immediately after initialization,
+ * and before any session is opened.
+ *
+ * @version
+ * This method is new in API version 16.
+ */
+OEMCryptoResult OEMCrypto_GenerateOTARequest(OEMCrypto_SESSION session,
+ uint8_t* buffer,
+ size_t* buffer_length,
+ uint32_t use_test_key);
+
+/**
+ * The buffer will be parsed as an OTA Keybox provisioning message, as
+ * described in the document OTA Keybox Reprovisioning. The
+ * signature will be verified. The keybox will be decrypted and verified. If
+ * |use_test_key| is false, the keybox will be installed permanently.
+ *
+ * If |use_test_key| is true, do not use the real model key, use the debug
+ * model key specified in OTA Keybox Reprovisioning.
+ *
+ * @param[in] session: handle for the session to be used.
+ * @param[in] buffer: pointer to provisioning response.
+ * @param[in] buffer_length: length of the buffer, in bytes.
+ * @param[in] use_test_key: If non-zero, use the debug model key. This is used
+ * for testing the workflow.
+ *
+ * @retval OEMCrypto_SUCCESS on success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_SIGNATURE_FAILURE signature of message was wrong.
+ * @retval OEMCrypto_ERROR_KEYBOX_INVALID if the keybox was unpacked, but is
+ * invalid.
+ * @retval OEMCrypto_ERROR_WRITE_KEYBOX could not save keybox.
+ * Any other error will be logged.
+ *
+ * @threading
+ * This is an "Initialization and Termination Function" and will not be called
+ * simultaneously with any other function, as if the CDM holds a write lock on
+ * the OEMCrypto system. It will only be called after
+ * OEMCrypto_GenerateOTARequest().
+ *
+ * @version
+ * This method is new in API version 16.
+ */
+OEMCryptoResult OEMCrypto_ProcessOTAKeybox(OEMCrypto_SESSION session,
+ const uint8_t* buffer,
+ size_t buffer_length,
+ uint32_t use_test_key);
+
+/****************************************************************************/
+/****************************************************************************/
+/* The following functions are deprecated. They are not required for the
+ * current version of OEMCrypto. They are being declared here to help with
+ * backwards compatibility.
+ */
+
+/*
+ * OEMCrypto_GenerateSignature
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ uint8_t* signature,
+ size_t* signature_length);
+
+/*
+ * OEMCrypto_RewrapDeviceRSAKey30
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
+ OEMCrypto_SESSION session, const uint32_t* unaligned_nonce,
+ const uint8_t* encrypted_message_key, size_t encrypted_message_key_length,
+ const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
+ const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key,
+ size_t* wrapped_rsa_key_length);
+
+/*
+ * OEMCrypto_RewrapDeviceRSAKey
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const uint8_t* signature, size_t signature_length,
+ const uint32_t* unaligned_nonce, const uint8_t* enc_rsa_key,
+ size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv,
+ uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length);
+
+/*
+ * OEMCrypto_UpdateUsageTable
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_UpdateUsageTable(void);
+
+/*
+ * OEMCrypto_DeleteUsageEntry
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_DeleteUsageEntry(
+ OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length,
+ const uint8_t* message, size_t message_length, const uint8_t* signature,
+ size_t signature_length);
+
+/*
+ * OEMCrypto_ForceDeleteUsageEntry
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(const uint8_t* pst,
+ size_t pst_length);
+
+/*
+ * OEMCrypto_CopyOldUsageEntry
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_CopyOldUsageEntry(OEMCrypto_SESSION session,
+ const uint8_t* pst,
+ size_t pst_length);
+
+/*
+ * OEMCrypto_DeleteOldUsageTable
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_DeleteOldUsageTable(void);
+
+/*
+ * OEMCrypto_CreateOldUsageEntry
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_CreateOldUsageEntry(
+ uint64_t time_since_license_received, uint64_t time_since_first_decrypt,
+ uint64_t time_since_last_decrypt, OEMCrypto_Usage_Entry_Status status,
+ uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
+ size_t pst_length);
+
+/*
+ * OEMCrypto_GenerateDerivedKeys_V15
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_GenerateDerivedKeys_V15(
+ OEMCrypto_SESSION session, const uint8_t* mac_key_context,
+ uint32_t mac_key_context_length, const uint8_t* enc_key_context,
+ uint32_t enc_key_context_length);
+
+typedef struct {
+ size_t encrypt; // number of 16 byte blocks to decrypt.
+ size_t skip; // number of 16 byte blocks to leave in clear.
+ size_t offset; // offset into the pattern in blocks for this call.
+} OEMCrypto_CENCEncryptPatternDesc_V15;
+
+/*
+ * OEMCrypto_DecryptCENC_V15
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_DecryptCENC_V15(
+ OEMCrypto_SESSION session, const uint8_t* data_addr,
+ size_t data_addr_length, bool is_encrypted, const uint8_t* iv,
+ size_t block_offset, // used for CTR "cenc" mode only.
+ OEMCrypto_DestBufferDesc* out_buffer,
+ const OEMCrypto_CENCEncryptPatternDesc_V15* pattern,
+ uint8_t subsample_flags);
+
+/*
+ * OEMCrypto_GetOEMPublicCertificate_V15
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_GetOEMPublicCertificate_V15(
+ OEMCrypto_SESSION session, uint8_t* public_cert,
+ size_t* public_cert_length);
+
+/*
+ * OEMCrypto_LoadDeviceRSAKey
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session,
+ const uint8_t* wrapped_rsa_key,
+ size_t wrapped_rsa_key_length);
+
+/*
+ * OEMCrypto_BuildInformation_V16
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+const char* OEMCrypto_BuildInformation_V16(void);
+
+/*
+ * OEMCrypto_SecurityLevel_V16
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+const char* OEMCrypto_SecurityLevel_V16(void);
+
+typedef struct {
+ OEMCrypto_Substring entitlement_key_id;
+ OEMCrypto_Substring content_key_id;
+ OEMCrypto_Substring content_key_data_iv;
+ OEMCrypto_Substring content_key_data;
+} OEMCrypto_EntitledContentKeyObject_V16;
+
+/*
+ * OEMCrypto_LoadEntitledContentKeys_V16
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_LoadEntitledContentKeys_V16(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ size_t key_array_length,
+ const OEMCrypto_EntitledContentKeyObject_V16* key_array);
+
+/**
+ * OEmCrypto_IsSRIMUpdateSupported
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+bool OEMCrypto_IsSRMUpdateSupported(void);
+
+/**
+ * OEMCrypto_LoadSRM
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer, size_t buffer_length);
+
+/**
+ * OEMCrypto_RemoveSRM
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_RemoveSRM(void);
+
+/**
+ * OEMCrypto_LoadKeys
+ * @deprecated
+ * OEMCrypto_LoadKeys is only used to load a v15 license or renewal.
+ */
+OEMCryptoResult OEMCrypto_LoadKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const uint8_t* signature, size_t signature_length,
+ OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys,
+ size_t key_array_length, const OEMCrypto_KeyObject* key_array,
+ OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data,
+ OEMCrypto_LicenseType license_type);
+
+typedef struct {
+ OEMCrypto_Substring key_id;
+ OEMCrypto_Substring key_control_iv;
+ OEMCrypto_Substring key_control;
+} OEMCrypto_KeyRefreshObject;
+/**
+ * OEMCrypto_RefreshKeys
+ * @deprecated
+ * OEMCrypto_RefreshKeys is only used to load a v15 license or renewal.
+ */
+OEMCryptoResult OEMCrypto_RefreshKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const uint8_t* signature, size_t signature_length, size_t num_keys,
+ const OEMCrypto_KeyRefreshObject* key_array);
+
+/**
+ * OEMCrypto_GetRandom
+ * @deprecated
+ * OEMCrypto_GetRandom is not needed to export random numbers.
+ */
+OEMCryptoResult OEMCrypto_GetRandom(uint8_t* random_data,
+ size_t random_data_length);
+
+/**
+ * OEMCrypto_SelectKey
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session,
+ const uint8_t* content_key_id,
+ size_t content_key_id_length,
+ OEMCryptoCipherMode cipher_mode);
+
+/**
+ * OEMCrypto_DecryptCENC_V17
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_DecryptCENC_V17(
+ OEMCrypto_SESSION session, const OEMCrypto_SampleDescription* samples,
+ size_t samples_length, const OEMCrypto_CENCEncryptPatternDesc* pattern);
+
+/**
+ * OEMCrypto_Generic_Encrypt_V17
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_Generic_Encrypt_V17(
+ OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* in_buffer,
+ size_t in_buffer_length, const uint8_t* iv, OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* out_buffer);
+
+/**
+ * OEMCrypto_Generic_Decrypt_V17
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_Generic_Decrypt_V17(
+ OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* in_buffer,
+ size_t in_buffer_length, const uint8_t* iv, OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* out_buffer);
+
+/**
+ * OEMCrypto_Generic_Sign_V17
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_Generic_Sign_V17(OEMCrypto_SESSION session,
+ const OEMCrypto_SharedMemory* buffer,
+ size_t buffer_length,
+ OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* signature,
+ size_t* signature_length);
+
+/**
+ * OEMCrypto_Generic_Verify_V17
+ * @deprecated
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ */
+OEMCryptoResult OEMCrypto_Generic_Verify_V17(
+ OEMCrypto_SESSION session, const OEMCrypto_SharedMemory* buffer,
+ size_t buffer_length, OEMCrypto_Algorithm algorithm,
+ const OEMCrypto_SharedMemory* signature, size_t signature_length);
+
+/****************************************************************************/
+/****************************************************************************/
+/* The following functions are used by internal L3 CDMs and are not required by
+ * other CDM implementations.
+ */
+
+/**
+ * Get the embedded Drm Certificate used by internal L3 CDMs.
+ *
+ * @param[out] public_cert where the certificate is stored.
+ * @param[in,out] public_cert_length the length, in bytes, of the certificate.
+ *
+ * @retval OEMCrypto_SUCCESS on success
+ * @retval OEMCrypto_ERROR_SHORT_BUFFER if public_cert_length is too small.
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ */
+OEMCryptoResult OEMCrypto_GetEmbeddedDrmCertificate(uint8_t* public_cert,
+ size_t* public_cert_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // OEMCRYPTO_CENC_H_
diff --git a/oemcrypto/include/OEMCryptoCENCCommon.h b/oemcrypto/include/OEMCryptoCENCCommon.h
new file mode 100644
index 0000000..7da8b45
--- /dev/null
+++ b/oemcrypto/include/OEMCryptoCENCCommon.h
@@ -0,0 +1,262 @@
+// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+/*********************************************************************
+ * OEMCryptoCENCCommon.h
+ *
+ * Common structures and error codes between WV servers and OEMCrypto.
+ *
+ *********************************************************************/
+
+#ifndef WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_
+#define WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @addtogroup common_types
+/// @{
+
+/* clang-format off */
+/** Error and result codes returned by OEMCrypto functions. */
+typedef enum OEMCryptoResult {
+ OEMCrypto_SUCCESS = 0,
+ OEMCrypto_ERROR_INIT_FAILED = 1,
+ OEMCrypto_ERROR_TERMINATE_FAILED = 2,
+ OEMCrypto_ERROR_OPEN_FAILURE = 3,
+ OEMCrypto_ERROR_CLOSE_FAILURE = 4,
+ OEMCrypto_ERROR_ENTER_SECURE_PLAYBACK_FAILED = 5, /* deprecated */
+ OEMCrypto_ERROR_EXIT_SECURE_PLAYBACK_FAILED = 6, /* deprecated */
+ OEMCrypto_ERROR_SHORT_BUFFER = 7,
+ OEMCrypto_ERROR_NO_DEVICE_KEY = 8, /* no keybox device key. */
+ OEMCrypto_ERROR_NO_ASSET_KEY = 9,
+ OEMCrypto_ERROR_KEYBOX_INVALID = 10,
+ OEMCrypto_ERROR_NO_KEYDATA = 11,
+ OEMCrypto_ERROR_NO_CW = 12,
+ OEMCrypto_ERROR_DECRYPT_FAILED = 13,
+ OEMCrypto_ERROR_WRITE_KEYBOX = 14,
+ OEMCrypto_ERROR_WRAP_KEYBOX = 15,
+ OEMCrypto_ERROR_BAD_MAGIC = 16,
+ OEMCrypto_ERROR_BAD_CRC = 17,
+ OEMCrypto_ERROR_NO_DEVICEID = 18,
+ OEMCrypto_ERROR_RNG_FAILED = 19,
+ OEMCrypto_ERROR_RNG_NOT_SUPPORTED = 20,
+ OEMCrypto_ERROR_SETUP = 21,
+ OEMCrypto_ERROR_OPEN_SESSION_FAILED = 22,
+ OEMCrypto_ERROR_CLOSE_SESSION_FAILED = 23,
+ OEMCrypto_ERROR_INVALID_SESSION = 24,
+ OEMCrypto_ERROR_NOT_IMPLEMENTED = 25,
+ OEMCrypto_ERROR_NO_CONTENT_KEY = 26,
+ OEMCrypto_ERROR_CONTROL_INVALID = 27,
+ OEMCrypto_ERROR_UNKNOWN_FAILURE = 28,
+ OEMCrypto_ERROR_INVALID_CONTEXT = 29,
+ OEMCrypto_ERROR_SIGNATURE_FAILURE = 30,
+ OEMCrypto_ERROR_TOO_MANY_SESSIONS = 31,
+ OEMCrypto_ERROR_INVALID_NONCE = 32,
+ OEMCrypto_ERROR_TOO_MANY_KEYS = 33,
+ OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED = 34,
+ OEMCrypto_ERROR_INVALID_RSA_KEY = 35, /* deprecated */
+ OEMCrypto_ERROR_KEY_EXPIRED = 36,
+ OEMCrypto_ERROR_INSUFFICIENT_RESOURCES = 37,
+ OEMCrypto_ERROR_INSUFFICIENT_HDCP = 38,
+ OEMCrypto_ERROR_BUFFER_TOO_LARGE = 39,
+ OEMCrypto_WARNING_GENERATION_SKEW = 40, /* Warning, not error. */
+ OEMCrypto_ERROR_GENERATION_SKEW = 41,
+ OEMCrypto_LOCAL_DISPLAY_ONLY = 42, /* Info, not an error. */
+ OEMCrypto_ERROR_ANALOG_OUTPUT = 43,
+ OEMCrypto_ERROR_WRONG_PST = 44,
+ OEMCrypto_ERROR_WRONG_KEYS = 45,
+ OEMCrypto_ERROR_MISSING_MASTER = 46,
+ OEMCrypto_ERROR_LICENSE_INACTIVE = 47,
+ OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE = 48,
+ OEMCrypto_ERROR_ENTRY_IN_USE = 49,
+ OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50, /* Obsolete. Don't use. */
+ /* Use OEMCrypto_ERROR_NO_CONTENT_KEY instead of KEY_NOT_LOADED. */
+ OEMCrypto_KEY_NOT_LOADED = 51, /* Obsolete. */
+ OEMCrypto_KEY_NOT_ENTITLED = 52,
+ OEMCrypto_ERROR_BAD_HASH = 53,
+ OEMCrypto_ERROR_OUTPUT_TOO_LARGE = 54,
+ OEMCrypto_ERROR_SESSION_LOST_STATE = 55,
+ OEMCrypto_ERROR_SYSTEM_INVALIDATED = 56,
+ OEMCrypto_ERROR_LICENSE_RELOAD = 57,
+ OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
+ OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
+ OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION = 60,
+ OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING = 61,
+ OEMCrypto_ERROR_UNSUPPORTED_CIPHER = 62,
+ OEMCrypto_ERROR_DVR_FORBIDDEN = 63,
+ OEMCrypto_ERROR_INSUFFICIENT_PRIVILEGE = 64,
+ OEMCrypto_ERROR_INVALID_KEY = 65,
+ /* ODK return values */
+ ODK_ERROR_BASE = 1000,
+ ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
+ ODK_SET_TIMER = ODK_ERROR_BASE + 1,
+ ODK_DISABLE_TIMER = ODK_ERROR_BASE + 2,
+ ODK_TIMER_EXPIRED = ODK_ERROR_BASE + 3,
+ ODK_UNSUPPORTED_API = ODK_ERROR_BASE + 4,
+ ODK_STALE_RENEWAL = ODK_ERROR_BASE + 5,
+ /* OPK return values */
+ OPK_ERROR_BASE = 2000,
+ OPK_ERROR_REMOTE_CALL = OPK_ERROR_BASE,
+ OPK_ERROR_INCOMPATIBLE_VERSION = OPK_ERROR_BASE + 1,
+ OPK_ERROR_NO_PERSISTENT_DATA = OPK_ERROR_BASE + 2,
+ OPK_ERROR_PREHOOK_FAILURE = OPK_ERROR_BASE + 3,
+ OPK_ERROR_POSTHOOK_FAILURE = OPK_ERROR_BASE + 4,
+} OEMCryptoResult;
+/* clang-format on */
+
+/**
+ * Valid values for status in the usage table.
+ */
+typedef enum OEMCrypto_Usage_Entry_Status {
+ kUnused = 0,
+ kActive = 1,
+ kInactive = 2, /* Deprecated. Use kInactiveUsed or kInactiveUnused. */
+ kInactiveUsed = 3,
+ kInactiveUnused = 4,
+} OEMCrypto_Usage_Entry_Status;
+
+/* Not used publicly. Not documented with Doxygen. */
+typedef enum OEMCrypto_ProvisioningRenewalType {
+ OEMCrypto_NoRenewal = 0,
+ OEMCrypto_RenewalACert = 1,
+} OEMCrypto_ProvisioningRenewalType;
+
+/**
+ * OEMCrypto_LicenseType is used in the license message to indicate if the key
+ * objects are for content keys, or for entitlement keys.
+ */
+typedef enum OEMCrypto_LicenseType {
+ OEMCrypto_ContentLicense = 0,
+ OEMCrypto_EntitlementLicense = 1,
+ OEMCrypto_LicenseType_MaxValue = OEMCrypto_EntitlementLicense,
+} OEMCrypto_LicenseType;
+
+/**
+ * Private key type used in the provisioning response.
+ */
+typedef enum OEMCrypto_PrivateKeyType {
+ OEMCrypto_RSA_Private_Key = 0,
+ OEMCrypto_ECC_Private_Key = 1,
+ OEMCrypto_PrivateKeyType_MaxValue = OEMCrypto_ECC_Private_Key,
+} OEMCrypto_PrivateKeyType;
+
+/**
+ * The base for (delayed) timers, i.e. from what time the (delayed) timer
+ * starts.
+ */
+typedef enum OEMCrypto_TimerDelayBase {
+ OEMCrypto_License_Start = 0,
+ OEMCrypto_License_Load = 1,
+ OEMCrypto_First_Decrypt = 2,
+ OEMCrypto_TimerDelayBase_MaxValue = OEMCrypto_First_Decrypt,
+} OEMCrypto_TimerDelayBase;
+
+/**
+ * Used to indicate a substring of a signed message in ODK_ParseLicense
+ * and other functions which must verify that a parameter is contained within a
+ * signed message.
+ */
+typedef struct {
+ size_t offset;
+ size_t length;
+} OEMCrypto_Substring;
+
+/**
+ * Used to specify information about CMI Descriptor 0.
+ * @param id: ID value of CMI Descriptor assigned by DTLA.
+ * @param length: byte length of the usage rules field.
+ * @param data: usage rules data.
+ */
+typedef struct {
+ uint8_t id; // 0x00
+ uint8_t extension; // 0x00
+ uint16_t length; // 0x01
+ uint8_t data;
+} OEMCrypto_DTCP2_CMI_Descriptor_0;
+
+/**
+ * Used to specify information about CMI Descriptor 1.
+ * @param id: ID value of CMI Descriptor assigned by DTLA.
+ * @param extension: specified by the CMI descriptor
+ * @param length: byte length of the usage rules field.
+ * @param data: usage rules data.
+ */
+typedef struct {
+ uint8_t id; // 0x01
+ uint8_t extension; // 0x00
+ uint16_t length; // 0x03
+ uint8_t data[3];
+} OEMCrypto_DTCP2_CMI_Descriptor_1;
+
+/**
+ * Used to specify information about CMI Descriptor 2.
+ * @param id: ID value of CMI Descriptor assigned by DTLA.
+ * @param extension: specified by the CMI descriptor
+ * @param length: byte length of the usage rules field.
+ * @param data: usage rules data.
+ */
+typedef struct {
+ uint8_t id; // 0x02
+ uint8_t extension; // 0x00
+ uint16_t length; // 0x03
+ uint8_t data[3];
+} OEMCrypto_DTCP2_CMI_Descriptor_2;
+
+/**
+ * Used to specify the required DTCP2 level. If dtcp2_required is 0, there are
+ * no requirements on any of the keys. If dtcp2_required is 1, any key with the
+ * kControlHDCPRequired bit set requires DTCP2 in its output.
+ * @param dtcp2_required: specifies whether dtcp2 is required. 0 = not required,
+ * 1 = DTCP2 required.
+ * @param cmi_descriptor_1: three bytes of CMI descriptor 1
+ */
+typedef struct {
+ uint8_t dtcp2_required; // 0 = not required. 1 = DTCP2 v1 required.
+ OEMCrypto_DTCP2_CMI_Descriptor_0 cmi_descriptor_0;
+ OEMCrypto_DTCP2_CMI_Descriptor_1 cmi_descriptor_1;
+ OEMCrypto_DTCP2_CMI_Descriptor_2 cmi_descriptor_2;
+} OEMCrypto_DTCP2_CMI_Packet;
+
+/**
+ * Points to the relevant fields for a content key. The fields are extracted
+ * from the License Response message offered to ODK_ParseLicense(). Each
+ * field points to one of the components of the key. Key data, key control,
+ * and both IV fields are 128 bits (16 bytes):
+ * @param key_id: the unique id of this key.
+ * @param key_id_length: the size of key_id. OEMCrypto may assume this is at
+ * most 16. However, OEMCrypto shall correctly handle key id lengths
+ * from 1 to 16 bytes.
+ * @param key_data_iv: the IV for performing AES-128-CBC decryption of the
+ * key_data field.
+ * @param key_data - the key data. It is encrypted (AES-128-CBC) with the
+ * session's derived encrypt key and the key_data_iv.
+ * @param key_control_iv: the IV for performing AES-128-CBC decryption of the
+ * key_control field.
+ * @param key_control: the key control block. It is encrypted (AES-128-CBC) with
+ * the content key from the key_data field.
+ *
+ * The memory for the OEMCrypto_KeyObject fields is allocated and freed
+ * by the caller of ODK_ParseLicense().
+ */
+typedef struct {
+ OEMCrypto_Substring key_id;
+ OEMCrypto_Substring key_data_iv;
+ OEMCrypto_Substring key_data;
+ OEMCrypto_Substring key_control_iv;
+ OEMCrypto_Substring key_control;
+} OEMCrypto_KeyObject;
+
+/// @}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WIDEVINE_ODK_INCLUDE_OEMCRYPTOCENCCOMMON_H_
diff --git a/oemcrypto/include/level3.h b/oemcrypto/include/level3.h
new file mode 100644
index 0000000..826c657
--- /dev/null
+++ b/oemcrypto/include/level3.h
@@ -0,0 +1,612 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+/*********************************************************************
+ * level3.h
+ *
+ * Reference APIs needed to support Widevine's crypto algorithms.
+ *********************************************************************/
+
+#ifndef LEVEL3_OEMCRYPTO_H_
+#define LEVEL3_OEMCRYPTO_H_
+
+#include
+#include
+
+#include "OEMCryptoCENC.h"
+#include "level3_file_system.h"
+
+// clang-format off
+#ifdef DYNAMIC_ADAPTER
+#define Level3_IsInApp _lcc00
+#define Level3_Initialize _lcc01
+#define Level3_Terminate _lcc02
+#define Level3_InstallKeyboxOrOEMCert _lcc03
+#define Level3_GetKeyData _lcc04
+#define Level3_IsKeyboxOrOEMCertValid _lcc05
+#define Level3_GetDeviceID _lcc07
+#define Level3_WrapKeyboxOrOEMCert _lcc08
+#define Level3_OpenSession _lcc09
+#define Level3_CloseSession _lcc10
+#define Level3_GenerateSignature _lcc13
+#define Level3_GenerateNonce _lcc14
+#define Level3_RewrapDeviceRSAKey _lcc18
+#define Level3_LoadDeviceRSAKey _lcc19
+#define Level3_DeriveKeysFromSessionKey _lcc21
+#define Level3_APIVersion _lcc22
+#define Level3_Generic_Encrypt_V17 _lcc24
+#define Level3_Generic_Decrypt_V17 _lcc25
+#define Level3_Generic_Sign_V17 _lcc26
+#define Level3_Generic_Verify_V17 _lcc27
+#define Level3_SupportsUsageTable _lcc29
+#define Level3_ReportUsage _lcc32
+#define Level3_GetMaxNumberOfSessions _lcc37
+#define Level3_GetNumberOfOpenSessions _lcc38
+#define Level3_IsAntiRollbackHwPresent _lcc39
+#define Level3_QueryKeyControl _lcc41
+#define Level3_GetHDCPCapability _lcc44
+#define Level3_LoadTestRSAKey _lcc45
+#define Level3_SecurityPatchLevel _lcc46
+#define Level3_GetProvisioningMethod _lcc49
+#define Level3_RewrapDeviceRSAKey30 _lcc51
+#define Level3_SupportedCertificates _lcc52
+#define Level3_IsSRMUpdateSupported _lcc53
+#define Level3_GetCurrentSRMVersion _lcc54
+#define Level3_LoadSRM _lcc55
+#define Level3_RemoveSRM _lcc57
+#define Level3_CreateUsageTableHeader _lcc61
+#define Level3_LoadUsageTableHeader _lcc62
+#define Level3_CreateNewUsageEntry _lcc63
+#define Level3_LoadUsageEntry _lcc64
+#define Level3_UpdateUsageEntry _lcc65
+#define Level3_ShrinkUsageTableHeader _lcc67
+#define Level3_MoveEntry _lcc68
+#define Level3_GetAnalogOutputFlags _lcc71
+#define Level3_LoadTestKeybox _lcc78
+#define Level3_SelectKey _lcc81
+#define Level3_LoadKeys _lcc83
+#define Level3_SetSandbox _lcc84
+#define Level3_ResourceRatingTier _lcc85
+#define Level3_SupportsDecryptHash _lcc86
+#define Level3_SetDecryptHash _lcc88
+#define Level3_GetHashErrorCode _lcc89
+#define Level3_RefreshKeys _lcc91
+#define Level3_LoadEntitledContentKeys_V16 _lcc92
+#define Level3_CopyBuffer _lcc93
+#define Level3_MaximumUsageTableHeaderSize _lcc94
+#define Level3_GenerateDerivedKeys _lcc95
+#define Level3_PrepAndSignLicenseRequest _lcc96
+#define Level3_PrepAndSignRenewalRequest _lcc97
+#define Level3_PrepAndSignProvisioningRequest _lcc98
+#define Level3_LoadLicense _lcc99
+#define Level3_LoadRenewal _lcc101
+#define Level3_LoadProvisioning _lcc102
+#define Level3_LoadOEMPrivateKey _lcc103
+#define Level3_GetOEMPublicCertificate _lcc104
+#define Level3_DecryptCENC_V17 _lcc105
+#define Level3_LoadDRMPrivateKey _lcc107
+#define Level3_MinorAPIVersion _lcc108
+#define Level3_AllocateSecureBuffer _lcc109
+#define Level3_FreeSecureBuffer _lcc110
+#define Level3_CreateEntitledKeySession _lcc111
+#define Level3_RemoveEntitledKeySession _lcc112
+#define Level3_GetBootCertificateChain _lcc116
+#define Level3_GenerateCertificateKeyPair _lcc117
+#define Level3_InstallOemPrivateKey _lcc118
+#define Level3_ReassociateEntitledKeySession _lcc119
+#define Level3_LoadCasECMKeys _lcc120
+#define Level3_LoadEntitledContentKeys _lcc121 // place holder for v17.
+#define Level3_ProductionReady _lcc122
+#define Level3_Idle _lcc123
+#define Level3_Wake _lcc124
+#define Level3_BuildInformation _lcc125
+#define Level3_SecurityLevel _lcc126
+#define Level3_ReuseUsageEntry _lcc127
+#define Level3_GetDTCP2Capability _lcc128
+#define Level3_GetWatermarkingSupport _lcc129
+#define Level3_GetOEMKeyToken _lcc130
+#define Level3_GetDeviceInformation _lcc131
+#define Level3_SetMaxAPIVersion _lcc132
+#define Level3_GetKeyHandle _lcc133
+#define Level3_DecryptCENC _lcc134
+#define Level3_Generic_Encrypt _lcc135
+#define Level3_Generic_Decrypt _lcc136
+#define Level3_Generic_Sign _lcc137
+#define Level3_Generic_Verify _lcc138
+#define Level3_GetSignatureHashAlgorithm _lcc139
+#define Level3_EnterTestMode _lcc140
+#define Level3_GetDeviceSignedCsrPayload _lcc141
+#define Level3_GetEmbeddedDrmCertificate _lcc143
+#else
+#define Level3_Initialize _oecc01
+#define Level3_Terminate _oecc02
+#define Level3_InstallKeyboxOrOEMCert _oecc03
+#define Level3_GetKeyData _oecc04
+#define Level3_IsKeyboxOrOEMCertValid _oecc05
+#define Level3_GetDeviceID _oecc07
+#define Level3_WrapKeyboxOrOEMCert _oecc08
+#define Level3_OpenSession _oecc09
+#define Level3_CloseSession _oecc10
+#define Level3_GenerateSignature _oecc13
+#define Level3_GenerateNonce _oecc14
+#define Level3_RewrapDeviceRSAKey _oecc18
+#define Level3_LoadDeviceRSAKey _oecc19
+#define Level3_DeriveKeysFromSessionKey _oecc21
+#define Level3_APIVersion _oecc22
+#define Level3_Generic_Encrypt_V17 _oecc24
+#define Level3_Generic_Decrypt_V17 _oecc25
+#define Level3_Generic_Sign_V17 _oecc26
+#define Level3_Generic_Verify_V17 _oecc27
+#define Level3_SupportsUsageTable _oecc29
+#define Level3_ReportUsage _oecc32
+#define Level3_GenerateRSASignature _oecc36
+#define Level3_GetMaxNumberOfSessions _oecc37
+#define Level3_GetNumberOfOpenSessions _oecc38
+#define Level3_IsAntiRollbackHwPresent _oecc39
+#define Level3_QueryKeyControl _oecc41
+#define Level3_GetHDCPCapability _oecc44
+#define Level3_LoadTestRSAKey _oecc45
+#define Level3_SecurityPatchLevel _oecc46
+#define Level3_GetProvisioningMethod _oecc49
+#define Level3_RewrapDeviceRSAKey30 _oecc51
+#define Level3_SupportedCertificates _oecc52
+#define Level3_IsSRMUpdateSupported _oecc53
+#define Level3_GetCurrentSRMVersion _oecc54
+#define Level3_LoadSRM _oecc55
+#define Level3_RemoveSRM _oecc57
+#define Level3_CreateUsageTableHeader _oecc61
+#define Level3_LoadUsageTableHeader _oecc62
+#define Level3_CreateNewUsageEntry _oecc63
+#define Level3_LoadUsageEntry _oecc64
+#define Level3_UpdateUsageEntry _oecc65
+#define Level3_DeactivateUsageEntry _oecc66
+#define Level3_ShrinkUsageTableHeader _oecc67
+#define Level3_MoveEntry _oecc68
+#define Level3_GetAnalogOutputFlags _oecc71
+#define Level3_LoadTestKeybox _oecc78
+#define Level3_SelectKey _oecc81
+#define Level3_LoadKeys _oecc83
+#define Level3_SetSandbox _oecc84
+#define Level3_ResourceRatingTier _oecc85
+#define Level3_SupportsDecryptHash _oecc86
+#define Level3_SetDecryptHash _oecc88
+#define Level3_GetHashErrorCode _oecc89
+#define Level3_RefreshKeys _oecc91
+#define Level3_LoadEntitledContentKeys_V16 _oecc92
+#define Level3_CopyBuffer _oecc93
+#define Level3_MaximumUsageTableHeaderSize _oecc94
+#define Level3_GenerateDerivedKeys _oecc95
+#define Level3_PrepAndSignLicenseRequest _oecc96
+#define Level3_PrepAndSignRenewalRequest _oecc97
+#define Level3_PrepAndSignProvisioningRequest _oecc98
+#define Level3_LoadLicense _oecc99
+#define Level3_LoadRenewal _oecc101
+#define Level3_LoadProvisioning _oecc102
+#define Level3_LoadOEMPrivateKey _oecc103
+#define Level3_GetOEMPublicCertificate _oecc104
+#define Level3_DecryptCENC_V17 _oecc105
+#define Level3_LoadDRMPrivateKey _oecc107
+#define Level3_MinorAPIVersion _oecc108
+#define Level3_AllocateSecureBuffer _oecc109
+#define Level3_FreeSecureBuffer _oecc110
+#define Level3_CreateEntitledKeySession _oecc111
+#define Level3_RemoveEntitledKeySession _oecc112
+#define Level3_GetBootCertificateChain _oecc116
+#define Level3_GenerateCertificateKeyPair _oecc117
+#define Level3_InstallOemPrivateKey _oecc118
+#define Level3_ReassociateEntitledKeySession _oecc119
+#define Level3_LoadCasECMKeys _oecc120
+#define Level3_LoadEntitledContentKeys _oecc121 // place holder for v17.
+#define Level3_ProductionReady _oecc122
+#define Level3_Idle _oecc123
+#define Level3_Wake _oecc124
+#define Level3_BuildInformation _oecc125
+#define Level3_SecurityLevel _oecc126
+#define Level3_ReuseUsageEntry _oecc127
+#define Level3_GetDTCP2Capability _oecc128
+#define Level3_GetWatermarkingSupport _oecc129
+#define Level3_GetOEMKeyToken _oecc130
+#define Level3_GetDeviceInformation _oecc131
+#define Level3_SetMaxAPIVersion _oecc132
+#define Level3_GetKeyHandle _oecc133
+#define Level3_DecryptCENC _oecc134
+#define Level3_Generic_Encrypt _oecc135
+#define Level3_Generic_Decrypt _oecc136
+#define Level3_Generic_Sign _oecc137
+#define Level3_Generic_Verify _oecc138
+#define Level3_GetSignatureHashAlgorithm _oecc139
+#define Level3_EnterTestMode _oecc140
+#define Level3_GetDeviceSignedCsrPayload _oecc141
+// Internal-only.
+#define Level3_GetEmbeddedDrmCertificate _oecc143
+#endif
+
+#define Level3_GetInitializationState _oecl3o01
+// clang-format on
+
+extern "C" {
+
+bool Level3_IsInApp();
+OEMCryptoResult Level3_Initialize(void);
+OEMCryptoResult Level3_Terminate(void);
+OEMCryptoResult Level3_OpenSession(OEMCrypto_SESSION* session);
+OEMCryptoResult Level3_CloseSession(OEMCrypto_SESSION session);
+OEMCryptoResult Level3_GenerateDerivedKeys(OEMCrypto_SESSION session,
+ const uint8_t* mac_key_context,
+ size_t mac_key_context_length,
+ const uint8_t* enc_key_context,
+ size_t enc_key_context_length);
+OEMCryptoResult Level3_GenerateNonce(OEMCrypto_SESSION session,
+ uint32_t* nonce);
+OEMCryptoResult Level3_QueryKeyControl(OEMCrypto_SESSION session,
+ const uint8_t* key_id,
+ size_t key_id_length,
+ uint8_t* key_control_block,
+ size_t* key_control_block_length);
+OEMCryptoResult Level3_DecryptCENC_V17(
+ OEMCrypto_SESSION session, const OEMCrypto_SampleDescription* samples,
+ size_t samples_length, const OEMCrypto_CENCEncryptPatternDesc* pattern);
+OEMCryptoResult Level3_InstallKeyboxOrOEMCert(const uint8_t* rot,
+ size_t rotLength);
+OEMCryptoResult Level3_IsKeyboxOrOEMCertValid(void);
+OEMCryptoResult Level3_WrapKeyboxOrOEMCert(const uint8_t* rot, size_t rotLength,
+ uint8_t* wrappedRot,
+ size_t* wrappedRotLength,
+ const uint8_t* transportKey,
+ size_t transportKeyLength);
+OEMCrypto_ProvisioningMethod Level3_GetProvisioningMethod();
+OEMCryptoResult Level3_GetOEMPublicCertificate(uint8_t* public_cert,
+ size_t* public_cert_length);
+OEMCryptoResult Level3_GetDeviceID(uint8_t* deviceID, size_t* idLength);
+OEMCryptoResult Level3_GetKeyData(uint8_t* keyData, size_t* keyDataLength);
+OEMCryptoResult Level3_LoadOEMPrivateKey(OEMCrypto_SESSION session);
+OEMCryptoResult Level3_LoadDRMPrivateKey(OEMCrypto_SESSION session,
+ OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_rsa_key,
+ size_t wrapped_rsa_key_length);
+OEMCryptoResult Level3_LoadProvisioning(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ size_t core_message_length, const uint8_t* signature,
+ size_t signature_length, uint8_t* wrapped_private_key,
+ size_t* wrapped_private_key_length);
+OEMCryptoResult Level3_RewrapDeviceRSAKey(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const uint8_t* signature, size_t signature_length, const uint32_t* nonce,
+ const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
+ const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key,
+ size_t* wrapped_rsa_key_length);
+OEMCryptoResult Level3_LoadTestRSAKey();
+OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ uint8_t* signature,
+ size_t* signature_length,
+ RSA_Padding_Scheme padding_scheme);
+OEMCryptoResult Level3_DeriveKeysFromSessionKey(OEMCrypto_SESSION session,
+ const uint8_t* enc_session_key,
+ size_t enc_session_key_length,
+ const uint8_t* mac_key_context,
+ size_t mac_key_context_length,
+ const uint8_t* enc_key_context,
+ size_t enc_key_context_length);
+uint32_t Level3_APIVersion();
+uint32_t Level3_MinorAPIVersion();
+uint8_t Level3_SecurityPatchLevel();
+OEMCrypto_Security_Level Level3_SecurityLevel();
+OEMCryptoResult Level3_GetHDCPCapability(OEMCrypto_HDCP_Capability* current,
+ OEMCrypto_HDCP_Capability* maximum);
+bool Level3_SupportsUsageTable();
+bool Level3_IsAntiRollbackHwPresent();
+OEMCryptoResult Level3_GetNumberOfOpenSessions(size_t* count);
+OEMCryptoResult Level3_GetMaxNumberOfSessions(size_t* maximum);
+uint32_t Level3_SupportedCertificates();
+OEMCryptoResult Level3_Generic_Encrypt_V17(
+ OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
+ const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer);
+OEMCryptoResult Level3_Generic_Decrypt_V17(
+ OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
+ const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer);
+OEMCryptoResult Level3_Generic_Sign_V17(OEMCrypto_SESSION session,
+ const uint8_t* in_buffer,
+ size_t buffer_length,
+ OEMCrypto_Algorithm algorithm,
+ uint8_t* signature,
+ size_t* signature_length);
+OEMCryptoResult Level3_Generic_Verify_V17(OEMCrypto_SESSION session,
+ const uint8_t* in_buffer,
+ size_t buffer_length,
+ OEMCrypto_Algorithm algorithm,
+ const uint8_t* signature,
+ size_t signature_length);
+OEMCryptoResult Level3_DeactivateUsageEntry(OEMCrypto_SESSION session,
+ const uint8_t* pst,
+ size_t pst_length);
+OEMCryptoResult Level3_ReportUsage(OEMCrypto_SESSION session,
+ const uint8_t* pst, size_t pst_length,
+ uint8_t* buffer, size_t* buffer_length);
+bool Level3_IsSRMUpdateSupported();
+OEMCryptoResult Level3_GetCurrentSRMVersion(uint16_t* version);
+OEMCryptoResult Level3_LoadSRM(const uint8_t* buffer, size_t buffer_length);
+OEMCryptoResult Level3_RemoveSRM();
+OEMCryptoResult Level3_CreateUsageTableHeader(uint8_t* header_buffer,
+ size_t* header_buffer_length);
+OEMCryptoResult Level3_LoadUsageTableHeader(const uint8_t* buffer,
+ size_t buffer_length);
+OEMCryptoResult Level3_CreateNewUsageEntry(OEMCrypto_SESSION session,
+ uint32_t* usage_entry_number);
+OEMCryptoResult Level3_LoadUsageEntry(OEMCrypto_SESSION session, uint32_t index,
+ const uint8_t* buffer,
+ size_t buffer_size);
+OEMCryptoResult Level3_UpdateUsageEntry(OEMCrypto_SESSION session,
+ uint8_t* header_buffer,
+ size_t* header_buffer_length,
+ uint8_t* entry_buffer,
+ size_t* entry_buffer_length);
+OEMCryptoResult Level3_ShrinkUsageTableHeader(uint32_t new_table_size,
+ uint8_t* header_buffer,
+ size_t* header_buffer_length);
+OEMCryptoResult Level3_MoveEntry(OEMCrypto_SESSION session, uint32_t new_index);
+uint32_t Level3_GetAnalogOutputFlags();
+OEMCryptoResult Level3_LoadTestKeybox(const uint8_t* buffer, size_t length);
+OEMCryptoResult Level3_SelectKey(const OEMCrypto_SESSION session,
+ const uint8_t* key_id, size_t key_id_length,
+ OEMCryptoCipherMode cipher_mode);
+OEMCryptoResult Level3_LoadLicense(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ size_t core_message_length,
+ const uint8_t* signature,
+ size_t signature_length);
+OEMCryptoResult Level3_LoadKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const uint8_t* signature, size_t signature_length,
+ OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys,
+ size_t num_keys, const OEMCrypto_KeyObject* key_array,
+ OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data,
+ OEMCrypto_LicenseType license_type);
+OEMCryptoResult Level3_SetSandbox(const uint8_t* sandbox_id,
+ size_t sandbox_id_length);
+uint32_t Level3_ResourceRatingTier();
+uint32_t Level3_SupportsDecryptHash();
+
+OEMCryptoResult Level3_SetDecryptHash(OEMCrypto_SESSION session,
+ uint32_t frame_number,
+ const uint8_t* hash, size_t hash_length);
+OEMCryptoResult Level3_GetHashErrorCode(OEMCrypto_SESSION session,
+ uint32_t* failed_frame_number);
+OEMCryptoResult Level3_BuildInformation(char* buffer, size_t* buffer_length);
+OEMCryptoResult Level3_LoadRenewal(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ size_t core_message_length,
+ const uint8_t* signature,
+ size_t signature_length);
+OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ const uint8_t* signature,
+ size_t signature_length, size_t num_keys,
+ const OEMCrypto_KeyRefreshObject* key_array);
+OEMCryptoResult Level3_LoadEntitledContentKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array);
+OEMCryptoResult Level3_CopyBuffer(
+ OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
+ const OEMCrypto_DestBufferDesc* out_buffer_descriptor,
+ uint8_t subsample_flags);
+OEMCryptoResult Level3_PrepAndSignProvisioningRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_length, uint8_t* signature, size_t* signature_length);
+OEMCryptoResult Level3_PrepAndSignLicenseRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_length, uint8_t* signature, size_t* signature_length);
+OEMCryptoResult Level3_PrepAndSignRenewalRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_length, uint8_t* signature, size_t* signature_length);
+size_t Level3_MaximumUsageTableHeaderSize();
+OEMCryptoResult Level3_AllocateSecureBuffer(
+ OEMCrypto_SESSION session, size_t buffer_size,
+ OEMCrypto_DestBufferDesc* output_descriptor, int* secure_fd);
+OEMCryptoResult Level3_FreeSecureBuffer(
+ OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor,
+ int secure_fd);
+OEMCryptoResult Level3_CreateEntitledKeySession(OEMCrypto_SESSION oec_session,
+ OEMCrypto_SESSION* key_session);
+OEMCryptoResult Level3_RemoveEntitledKeySession(OEMCrypto_SESSION key_session);
+OEMCryptoResult Level3_GetBootCertificateChain(
+ uint8_t* bcc, size_t* bcc_size, uint8_t* additional_signature,
+ size_t* additional_signature_size);
+OEMCryptoResult Level3_GenerateCertificateKeyPair(
+ OEMCrypto_SESSION session, uint8_t* public_key, size_t* public_key_size,
+ uint8_t* public_key_signature, size_t* public_key_signature_size,
+ uint8_t* wrapped_private_key, size_t* wrapped_private_key_size,
+ OEMCrypto_PrivateKeyType* key_type);
+OEMCryptoResult Level3_InstallOemPrivateKey(OEMCrypto_SESSION session,
+ OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key,
+ size_t wrapped_private_key_length);
+OEMCryptoResult Level3_ReassociateEntitledKeySession(
+ OEMCrypto_SESSION key_session, OEMCrypto_SESSION oec_session);
+OEMCryptoResult Level3_LoadCasECMKeys(
+ OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
+ const OEMCrypto_EntitledContentKeyObject* even_key,
+ const OEMCrypto_EntitledContentKeyObject* odd_key);
+OEMCryptoResult Level3_ProductionReady();
+OEMCryptoResult Level3_Idle(OEMCrypto_IdleState state,
+ uint32_t os_specific_code);
+OEMCryptoResult Level3_Wake();
+OEMCryptoResult Level3_ReuseUsageEntry(OEMCrypto_SESSION session,
+ uint32_t usage_entry_number);
+OEMCryptoResult Level3_GetDTCP2Capability(
+ OEMCrypto_DTCP2_Capability* capability);
+OEMCrypto_WatermarkingSupport Level3_GetWatermarkingSupport();
+OEMCryptoResult Level3_GetOEMKeyToken(OEMCrypto_SESSION key_session,
+ uint8_t* key_token,
+ size_t* key_token_length);
+OEMCryptoResult Level3_GetDeviceInformation(uint8_t* device_info,
+ size_t* device_info_length);
+OEMCryptoResult Level3_GetDeviceSignedCsrPayload(
+ const uint8_t* challenge, size_t challenge_length,
+ const uint8_t* encoded_device_info, size_t encoded_device_info_length,
+ uint8_t* signed_csr_payload, size_t* signed_csr_payload_length);
+OEMCryptoResult Level3_SetMaxAPIVersion(uint32_t max_version);
+OEMCryptoResult Level3_GetKeyHandle(OEMCrypto_SESSION session,
+ const uint8_t* content_key_id,
+ size_t content_key_id_length,
+ OEMCryptoCipherMode cipher_mode,
+ uint8_t* key_handle,
+ size_t* key_handle_length);
+OEMCryptoResult Level3_DecryptCENC(
+ const uint8_t* key_handle, size_t key_handle_length,
+ const OEMCrypto_SampleDescription* samples, size_t samples_length,
+ const OEMCrypto_CENCEncryptPatternDesc* pattern);
+OEMCryptoResult Level3_Generic_Encrypt(const uint8_t* key_handle,
+ size_t key_handle_length,
+ const OEMCrypto_SharedMemory* in_buffer,
+ size_t in_buffer_length,
+ const uint8_t* iv,
+ OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* out_buffer);
+OEMCryptoResult Level3_Generic_Decrypt(const uint8_t* key_handle,
+ size_t key_handle_length,
+ const OEMCrypto_SharedMemory* in_buffer,
+ size_t in_buffer_length,
+ const uint8_t* iv,
+ OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* out_buffer);
+OEMCryptoResult Level3_Generic_Sign(const uint8_t* key_handle,
+ size_t key_handle_length,
+ const OEMCrypto_SharedMemory* buffer,
+ size_t buffer_length,
+ OEMCrypto_Algorithm algorithm,
+ OEMCrypto_SharedMemory* signature,
+ size_t* signature_length);
+OEMCryptoResult Level3_Generic_Verify(const uint8_t* key_handle,
+ size_t key_handle_length,
+ const OEMCrypto_SharedMemory* buffer,
+ size_t buffer_length,
+ OEMCrypto_Algorithm algorithm,
+ const OEMCrypto_SharedMemory* signature,
+ size_t signature_length);
+OEMCryptoResult Level3_GetSignatureHashAlgorithm(
+ OEMCrypto_SESSION session, OEMCrypto_SignatureHashAlgorithm* algorithm);
+OEMCryptoResult Level3_EnterTestMode(void);
+OEMCryptoResult Level3_GetEmbeddedDrmCertificate(uint8_t* public_cert,
+ size_t* public_cert_length);
+
+// The following are specific to Google's Level 3 implementation and are not
+// required.
+
+enum Level3InitializationState {
+ LEVEL3_INITIALIZATION_SUCCESS = 0,
+ LEVEL3_INITIALIZATION_UNKNOWN_FAILURE = 1,
+ LEVEL3_SEED_FAILURE = 2,
+ LEVEL3_SAVE_DEVICE_KEYS_FAILURE = 3,
+ LEVEL3_READ_DEVICE_KEYS_FAILURE = 4,
+ LEVEL3_VERIFY_DEVICE_KEYS_FAILURE = 5,
+};
+
+enum Level3RunningMode {
+ LEVEL3_MODE_HAYSTACK_ONLY = 0,
+ LEVEL3_MODE_RIKERS_DEFAULT = 1,
+ LEVEL3_MODE_RIKERS_ONLY = 2,
+};
+
+/*
+ * Level3_GetRunningMode
+ *
+ * Description:
+ * Returns the current mode the Level3 is running in. This shouldn't change
+ * while the processes is running.
+ *
+ * Parameters:
+ * N/A
+ *
+ * Threading:
+ * No other function calls will be made while this function is running.
+ *
+ * Version:
+ * This method is new in API version 19.
+ */
+Level3RunningMode Level3_GetRunningMode(void);
+
+/*
+ * Level3_GetInitializationState
+ *
+ * Description:
+ * Return any warning or error condition which occurred during
+ * initialization. On some platforms, this value will be logged and metrics
+ * will be gathered on production devices. This is an optional feature, and
+ * OEMCrypto may always return 0, even if Level3_Initialize failed. This
+ * function may be called whether Level3_Initialize succeeded or not.
+ *
+ * Parameters:
+ * N/A
+ *
+ * Threading:
+ * No other function calls will be made while this function is running.
+ *
+ * Returns:
+ * LEVEL3_INITIALIZATION_SUCCESS - no warnings or errors during initialization
+ * LEVEL3_SEED_FAILURE - error in seeding the software RNG
+ * LEVEL3_SAVE_DEVICE_KEYS_FAILURE - failed to save device keys to file system
+ * LEVEL3_READ_DEVICE_KEYS_FAILURE - failed to read device keys from file
+ * system
+ * LEVEL3_VERIFY_DEVICE_KEYS_FAILURE - failed to verify decrypted device keys
+ *
+ * Version:
+ * This method is new in API version 14.
+ */
+Level3InitializationState Level3_GetInitializationState(void);
+
+/*
+ * Level3_OutputErrorLogs
+ *
+ * Description:
+ * Call to output any errors in the Level 3 execution if the Level 3 has
+ * failed. This method should only be called if the Level 3 has failed in
+ * an unrecoverable state, and needs to be reinitialized.
+ *
+ * Parameters:
+ * N/A
+ *
+ * Threading:
+ * No other function calls will be made while this function is running.
+ *
+ * Returns:
+ * N/A
+ *
+ * Version:
+ * This method is new in API version 15.
+ */
+void Level3_OutputErrorLogs();
+
+} // extern "C"
+
+namespace wvoec3 {
+
+// The following are interfaces needed for Google's Level 3 OEMCrypto
+// specifically, which partners are expected to implement.
+
+// Returns a stable, unique identifier for the device. This could be a
+// serial number or any other character sequence representing that device.
+// The parameter |len| needs to be changed to reflect the length of the
+// unique identifier.
+const char* getUniqueID(size_t* len);
+
+// Returns a 64-bit unsigned integer to be used as a random seed for RNG.
+// If the operation is unsuccessful, this function returns 0.
+// We provide a sample implementation under the name generate_entropy_linux.cpp
+// which partners should use if they can.
+uint64_t generate_entropy();
+
+// Creates and returns an OEMCrypto_Level3FileSystem implementation.
+OEMCrypto_Level3FileSystem* createLevel3FileSystem();
+
+// Deletes the pointer retrieved by the function above.
+void deleteLevel3FileSystem(OEMCrypto_Level3FileSystem* file_system);
+
+} // namespace wvoec3
+
+#endif // LEVEL3_OEMCRYPTO_H_
diff --git a/oemcrypto/include/level3_file_system.h b/oemcrypto/include/level3_file_system.h
new file mode 100644
index 0000000..8f8fbc3
--- /dev/null
+++ b/oemcrypto/include/level3_file_system.h
@@ -0,0 +1,32 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+/*********************************************************************
+ * level3_file_system.h
+ *
+ * File system for OEMCrypto Level3 file operations.
+ *********************************************************************/
+
+#ifndef LEVEL3_FILE_SYSTEM_H_
+#define LEVEL3_FILE_SYSTEM_H_
+
+#include
+#include "platform.h"
+
+namespace wvoec3 {
+
+class OEMCrypto_Level3FileSystem {
+ public:
+ virtual ~OEMCrypto_Level3FileSystem() {}
+ virtual ssize_t Read(const char *filename, void *buffer, size_t size) = 0;
+ virtual ssize_t Write(const char *filename, const void *buffer,
+ size_t size) = 0;
+ virtual bool Exists(const char *filename) = 0;
+ virtual ssize_t FileSize(const char *filename) = 0;
+ virtual bool Remove(const char *filename) = 0;
+};
+
+} // namespace wvoec3
+
+#endif
diff --git a/oemcrypto/include/oemcrypto_types.h b/oemcrypto/include/oemcrypto_types.h
new file mode 100644
index 0000000..02edc98
--- /dev/null
+++ b/oemcrypto/include/oemcrypto_types.h
@@ -0,0 +1,96 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+#ifndef WV_OEMCRYPTO_TYPES_H_
+#define WV_OEMCRYPTO_TYPES_H_
+
+#include
+
+namespace wvoec {
+
+// This is the format of a Widevine keybox.
+typedef struct WidevineKeybox { // 128 bytes total.
+ // C character string identifying the device. Null terminated.
+ uint8_t device_id_[32];
+ // 128 bit AES key assigned to device. Generated by Widevine.
+ uint8_t device_key_[16];
+ // Key Data. Encrypted data.
+ uint8_t data_[72];
+ // Constant code used to recognize a valid keybox "kbox" = 0x6b626f78.
+ uint8_t magic_[4];
+ // The CRC checksum of the first 124 bytes of the keybox.
+ uint8_t crc_[4];
+} WidevineKeybox;
+
+// This is the format for a key control block.
+typedef struct {
+ uint8_t verification[4];
+ uint32_t duration;
+ uint32_t nonce;
+ uint32_t control_bits;
+} KeyControlBlock;
+
+/*
+ * SRM_Restriction_Data
+ *
+ * Structure passed into LoadKeys to specify required SRM version.
+ */
+typedef struct {
+ uint8_t verification[8]; // must be "HDCPDATA"
+ uint32_t minimum_srm_version; // version number.
+} SRM_Restriction_Data;
+
+// clang-format off
+// Key Control Block Bit Masks:
+const uint32_t kControlObserveDataPath = (1u << 31);
+const uint32_t kControlObserveHDCP = (1u << 30);
+const uint32_t kControlObserveCGMS = (1u << 29);
+const uint32_t kControlRequireAntiRollbackHardware = (1u << 28);
+// The two bits kControlWhiteboxSecurityLevelMask are not used in
+// OEMCrypto; they are only used for whitebox testing.
+const uint32_t kControlWhiteboxSecurityLevelShift = 26;
+const uint32_t kControlWhiteboxSecurityLevelMask =
+ (0x03u << kControlWhiteboxSecurityLevelShift);
+const uint32_t kControlAllowDVRRecording = (1u << 25);
+const uint32_t kControlAllowHashVerification = (1u << 24);
+const uint32_t kSharedLicense = (1u << 23);
+const uint32_t kControlSRMVersionRequired = (1u << 22);
+const uint32_t kControlDisableAnalogOutput = (1u << 21);
+const uint32_t kControlSecurityPatchLevelShift = 15;
+const uint32_t kControlSecurityPatchLevelMask =
+ (0x3Fu << kControlSecurityPatchLevelShift);
+const uint32_t kControlReplayMask = (0x03u << 13);
+const uint32_t kControlNonceRequired = (0x01u << 13);
+const uint32_t kControlNonceOrEntry = (0x02u << 13);
+const uint32_t kControlHDCPVersionShift = 9;
+const uint32_t kControlHDCPVersionMask =
+ (0x0Fu << kControlHDCPVersionShift);
+const uint32_t kControlAllowEncrypt = (1u << 8);
+const uint32_t kControlAllowDecrypt = (1u << 7);
+const uint32_t kControlAllowSign = (1u << 6);
+const uint32_t kControlAllowVerify = (1u << 5);
+const uint32_t kControlDataPathSecure = (1u << 4);
+const uint32_t kControlNonceEnabled = (1u << 3);
+const uint32_t kControlHDCPRequired = (1u << 2);
+const uint32_t kControlCGMSMask = (0x03);
+const uint32_t kControlCGMSCopyFreely = (0x00);
+const uint32_t kControlCGMSCopyOnce = (0x02);
+const uint32_t kControlCGMSCopyNever = (0x03);
+// clang-format on
+
+// Various constants and sizes:
+constexpr size_t KEY_CONTROL_SIZE = 16;
+constexpr size_t KEY_ID_SIZE = 16;
+constexpr size_t KEY_IV_SIZE = 16;
+constexpr size_t KEY_PAD_SIZE = 16;
+constexpr size_t KEY_SIZE = 16;
+constexpr size_t AES_128_BLOCK_SIZE = 16;
+constexpr size_t MAC_KEY_SIZE = 32;
+constexpr size_t KEYBOX_KEY_DATA_SIZE = 72;
+constexpr size_t SRM_REQUIREMENT_SIZE = 12;
+constexpr size_t HMAC_SHA256_SIGNATURE_SIZE = 32;
+
+} // namespace wvoec
+
+#endif // WV_OEMCRYPTO_TYPES_H_
diff --git a/oemcrypto/include/pst_report.h b/oemcrypto/include/pst_report.h
new file mode 100644
index 0000000..33a1288
--- /dev/null
+++ b/oemcrypto/include/pst_report.h
@@ -0,0 +1,148 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+/*********************************************************************
+ * pst_report.h
+ *
+ * Reference APIs needed to support Widevine's crypto algorithms.
+ *********************************************************************/
+
+#ifndef PST_REPORT_H_
+#define PST_REPORT_H_
+
+#include
+#include
+#include
+
+#include "OEMCryptoCENC.h"
+#include "string_conversions.h" // needed for htonll64.
+
+namespace wvutil {
+
+class Unpacked_PST_Report {
+ public:
+ // This object does not own the buffer, and does not check that buffer
+ // is not null.
+ Unpacked_PST_Report(uint8_t *buffer) : buffer_(buffer) {}
+
+ // Copy and move semantics of this class is like that of a pointer.
+ Unpacked_PST_Report(const Unpacked_PST_Report& other) :
+ buffer_(other.buffer_) {}
+
+ Unpacked_PST_Report& operator=(const Unpacked_PST_Report& other) {
+ buffer_ = other.buffer_;
+ return *this;
+ }
+
+ size_t report_size() const {
+ return pst_length() + kraw_pst_report_size;
+ }
+
+ static size_t report_size(size_t pst_length) {
+ return pst_length + kraw_pst_report_size;
+ }
+
+ uint8_t status() const {
+ return static_cast(* (buffer_ + kstatus_offset));
+ }
+
+ void set_status(uint8_t value) {
+ buffer_[kstatus_offset] = value;
+ }
+
+ uint8_t* signature() {
+ return buffer_ + ksignature_offset;
+ }
+
+ uint8_t clock_security_level() const {
+ return static_cast(* (buffer_ + kclock_security_level_offset));
+ }
+
+ void set_clock_security_level(uint8_t value) {
+ buffer_[kclock_security_level_offset] = value;
+ }
+
+ uint8_t pst_length() const {
+ return static_cast(* (buffer_ + kpst_length_offset));
+ }
+
+ void set_pst_length(uint8_t value) {
+ buffer_[kpst_length_offset] = value;
+ }
+
+ uint8_t padding() const {
+ return static_cast(* (buffer_ + kpadding_offset));
+ }
+
+ void set_padding(uint8_t value) {
+ buffer_[kpadding_offset] = value;
+ }
+
+ // In host byte order.
+ int64_t seconds_since_license_received() const {
+ int64_t time;
+ memcpy(&time, buffer_ + kseconds_since_license_received_offset,
+ sizeof(int64_t));
+ return wvutil::ntohll64(time);
+ }
+
+ // Parameter time is in host byte order.
+ void set_seconds_since_license_received(int64_t time) const {
+ time = wvutil::ntohll64(time);
+ memcpy(buffer_ + kseconds_since_license_received_offset, &time,
+ sizeof(int64_t));
+ }
+
+ // In host byte order.
+ int64_t seconds_since_first_decrypt() const {
+ int64_t time;
+ memcpy(&time, buffer_ + kseconds_since_first_decrypt_offset,
+ sizeof(int64_t));
+ return ntohll64(time);
+ }
+
+ // Parameter time is in host byte order.
+ void set_seconds_since_first_decrypt(int64_t time) const {
+ time = ntohll64(time);
+ memcpy(buffer_ + kseconds_since_first_decrypt_offset, &time,
+ sizeof(int64_t));
+ }
+
+ // In host byte order.
+ int64_t seconds_since_last_decrypt() const {
+ int64_t time;
+ memcpy(&time, buffer_ + kseconds_since_last_decrypt_offset,
+ sizeof(int64_t));
+ return ntohll64(time);
+ }
+
+ // Parameter time is in host byte order.
+ void set_seconds_since_last_decrypt(int64_t time) const {
+ time = ntohll64(time);
+ memcpy(buffer_ + kseconds_since_last_decrypt_offset, &time,
+ sizeof(int64_t));
+ }
+
+ uint8_t* pst() {
+ return (buffer_ + kpst_offset);
+ }
+
+ private:
+ uint8_t *buffer_;
+
+ // Size of the PST_Report without the pst string.
+ static const size_t kraw_pst_report_size = 48;
+ static const size_t ksignature_offset = 0;
+ static const size_t kstatus_offset = 20;
+ static const size_t kclock_security_level_offset = 21;
+ static const size_t kpst_length_offset = 22;
+ static const size_t kpadding_offset = 23;
+ static const size_t kseconds_since_license_received_offset = 24;
+ static const size_t kseconds_since_first_decrypt_offset = 32;
+ static const size_t kseconds_since_last_decrypt_offset = 40;
+ static const size_t kpst_offset = 48;
+};
+} // namespace wvutil
+
+#endif // PST_REPORT_H_
diff --git a/plugin/Android.bp b/plugin/Android.bp
new file mode 100644
index 0000000..f64f89c
--- /dev/null
+++ b/plugin/Android.bp
@@ -0,0 +1,36 @@
+cc_library_static {
+ name: "libwvcasplugins",
+ local_include_dirs: [
+ "include",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "src/crypto_session.cpp",
+ "src/widevine_cas_session_map.cpp",
+ "src/widevine_media_cas.cpp",
+ "src/cas_license.cpp",
+ "src/ecm_parser.cpp",
+ "src/ecm_parser_v2.cpp",
+ "src/ecm_parser_v3.cpp",
+ "src/emm_parser.cpp",
+ "src/license_key_status.cpp",
+ "src/oemcrypto_interface.cpp",
+ "src/policy_engine.cpp",
+ "src/widevine_cas_session.cpp",
+ "src/widevine_media_cas_plugin.cpp",
+ "src/widevine_cas_api.cpp",
+ ],
+ proprietary: true,
+ shared_libs: [
+ "libcrypto",
+ "libutils",
+ ],
+ static_libs: [
+ "//vendor/widevine/libwvmediacas/wvutil:libcasutil",
+ "//vendor/widevine/libwvmediacas/protos:libcas_protos",
+ ],
+ header_libs: [
+ "//vendor/widevine/libwvmediacas/oemcrypto:oemcastroheaders",
+ "media_plugin_headers",
+ ],
+}
diff --git a/plugin/include/cas_events.h b/plugin/include/cas_events.h
new file mode 100644
index 0000000..af9955d
--- /dev/null
+++ b/plugin/include/cas_events.h
@@ -0,0 +1,128 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine Master
+// License Agreement.
+
+#ifndef CAS_EVENTS_H
+#define CAS_EVENTS_H
+
+#define PROVISIONING_EVENT_START 1000
+#define LICENSING_EVENT_START 2000
+#define CAS_SESSION_EVENT_START 3000
+#define CAS_QUERY_EVENT_START 4000
+#define CAS_ERROR_EVENT_START 5000
+#define CAS_PARENTAL_CONTROL_EVENT_START 6000
+#define CAS_FINGERPRINTING_EVENT_START 6100
+#define CAS_SERVICE_BLOCKING_EVENT_START 6200
+#define CAS_TEST_EVENT_START 10000
+
+typedef enum {
+ UNKNOWN = 0,
+
+ INDIVIDUALIZATION_REQUEST = PROVISIONING_EVENT_START,
+ INDIVIDUALIZATION_RESPONSE,
+ INDIVIDUALIZATION_COMPLETE,
+
+ LICENSE_REQUEST = LICENSING_EVENT_START,
+ LICENSE_RESPONSE,
+ CAS_ERROR_DEPRECATED,
+ LICENSE_RENEWAL_REQUEST,
+ LICENSE_RENEWAL_RESPONSE,
+ LICENSE_RENEWAL_URL,
+ LICENSE_CAS_READY,
+ LICENSE_CAS_RENEWAL_READY,
+ LICENSE_REMOVAL,
+ LICENSE_REMOVED,
+ ASSIGN_LICENSE_ID,
+ LICENSE_ID_ASSIGNED,
+ LICENSE_NEW_EXPIRY_TIME,
+ MULTI_CONTENT_LICENSE_INFO,
+ GROUP_LICENSE_INFO,
+ LICENSE_ENTITLEMENT_PERIOD_UPDATE_REQUEST,
+ LICENSE_ENTITLEMENT_PERIOD_UPDATE_RESPONSE,
+ LICENSE_ENTITLEMENT_PERIOD_UPDATED,
+
+ // TODO(jfore): Evaluate removing this event in favor of return status codes
+ // from
+ // frameworks/av/media/libstagefright/include/media/stagefright/MediaErrors.h
+ CAS_ERROR = CAS_ERROR_EVENT_START,
+
+ CAS_SESSION_ID = CAS_SESSION_EVENT_START,
+ SET_CAS_SOC_ID,
+ SET_CAS_SOC_DATA,
+
+ UNIQUE_ID = CAS_QUERY_EVENT_START,
+ QUERY_UNIQUE_ID,
+ WV_CAS_PLUGIN_VERSION,
+ QUERY_WV_CAS_PLUGIN_VERSION,
+
+ SET_PARENTAL_CONTROL_AGE = CAS_PARENTAL_CONTROL_EVENT_START,
+ DEPRECATED_PARENTAL_CONTROL_AGE_UPDATED,
+ ACCESS_DENIED_BY_PARENTAL_CONTROL,
+ AGE_RESTRICTION_UPDATED,
+
+ // The content of FINGERPRINTING_INFO events follows TLV (Type (1 byte) -
+ // Length (2 bytes) - Value) format. See FingerprintingFieldType for possible
+ // types. A FINGERPRINTING_INFO event contains {one or more CHANNEL, one
+ // CONTROL}.
+ FINGERPRINTING_INFO = CAS_FINGERPRINTING_EVENT_START,
+ // Fingerprinting control info for a session. The content of the event follows
+ // TLV (Type (1 byte) - Length (2 bytes) - Value) format. See
+ // SessionFingerprintingFieldType for possible types. It will contain {one
+ // FINGERPRINTING_CONTROL}.
+ SESSION_FINGERPRINTING_INFO,
+
+ // The content of SERVICE_BLOCKING_INFO events follows TLV (Type (1 byte) -
+ // Length (2 bytes) - Value) format. See ServiceBlockingFieldType for possible
+ // types. A SERVICE_BLOCKING_INFO event contains {one or more CHANNEL, one or
+ // more DEVICE_GROUP, zero or one START_TIME_SECONDS, one END_TIME_SECONDS}.
+ SERVICE_BLOCKING_INFO = CAS_SERVICE_BLOCKING_EVENT_START,
+ // Service blocking device group for a session. The content of the event
+ // follows TLV (Type (1 byte) - Length (2 bytes) - Value) format. See
+ // SessionServiceBlockingFieldType for possible types. It will contain {one or
+ // more SERVICE_BLOCKING_DEVICE_GROUP}.
+ SESSION_SERVICE_BLOCKING_INFO,
+
+ TEST_FOR_ECHO =
+ CAS_TEST_EVENT_START, // Request an ECHO response to test events passing.
+ ECHO, // Respond to TEST_FOR_ECHO.
+} CasEventId;
+
+// Types used inside an FINGERPRINTING_INFO event.
+typedef enum {
+ FINGERPRINTING_CHANNEL = 0,
+ FINGERPRINTING_CONTROL,
+} FingerprintingFieldType;
+
+// Types used inside an SERVICE_BLOCKING_INFO event.
+typedef enum {
+ SERVICE_BLOCKING_CHANNEL = 0,
+ SERVICE_BLOCKING_DEVICE_GROUP,
+ // Epoch time in seconds. Missing of this field or a value of 0 means
+ // immediate start.
+ SERVICE_BLOCKING_START_TIME_SECONDS,
+ SERVICE_BLOCKING_END_TIME_SECONDS, // Epoch time in seconds.
+} ServiceBlockingFieldType;
+
+// Types used inside an SESSION_FINGERPRINTING_CONTROL event.
+typedef enum {
+ SESSION_FINGERPRINTING_CONTROL = 0,
+} SessionFingerprintingFieldType;
+
+// Types used inside an SESSION_SERVICE_BLOCKING_GROUPS event.
+typedef enum {
+ SESSION_SERVICE_BLOCKING_DEVICE_GROUP = 0,
+} SessionServiceBlockingFieldType;
+
+// Types used inside a MULTI_CONTENT_LICENSE_INFO event.
+typedef enum {
+ MULTI_CONTENT_LICENSE_ID = 0,
+ MULTI_CONTENT_LICENSE_CONTENT_ID,
+} MultiContentLicenseFieldType;
+
+// Types used inside a GROUP_LICENSE_INFO event.
+typedef enum {
+ GROUP_LICENSE_ID = 0,
+ GROUP_LICENSE_GROUP_ID,
+} GroupLicenseFieldType;
+
+#endif // CAS_EVENTS_H
diff --git a/plugin/include/cas_license.h b/plugin/include/cas_license.h
new file mode 100644
index 0000000..b79acc3
--- /dev/null
+++ b/plugin/include/cas_license.h
@@ -0,0 +1,184 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine Master
+// License Agreement.
+
+#ifndef CAS_LICENSE_H
+#define CAS_LICENSE_H
+
+#include
+#include
+
+#include "cas_status.h"
+#include "crypto_session.h"
+#include "policy_engine.h"
+#include "timer.h"
+
+namespace wvcas {
+
+// CasLicense implements the core functionality needed to interact with service
+// to obtain and manage entitlements.
+class CasLicense : public wvutil::TimerHandler, public wvcas::CasEventListener {
+ public:
+ CasLicense() {}
+ virtual ~CasLicense() {}
+ // Initialize CasLicense with a |crypto_session|. |listener| may be null.
+ virtual CasStatus initialize(std::shared_ptr crypto_session,
+ CasEventListener* listener);
+
+ // Generate a request to obtain a device certificate for requesting
+ // entitlements. The generated message is set in |provisioning_request|.
+ virtual CasStatus GenerateDeviceProvisioningRequest(
+ std::string* provisioning_request) const;
+
+ // Process a server response containing a device certificate for use in
+ // requesting entitlements. The contained certificate data will be extracted
+ // and wrapped for storage. The public key cert will be returned in
+ // |device_certificate|. The private key information will be wrapped by the
+ // crypto session and returned in |wrapped_rsa_key|.
+ // A secure binary file image containing the device cert is returned in
+ // |device_file| if not nullptr. This file is suitable for storage on a device
+ virtual CasStatus HandleDeviceProvisioningResponse(
+ const std::string& signed_provisioning_response,
+ std::string* device_certificate, std::string* wrapped_rsa_key,
+ std::string* device_file) const;
+
+ // Generate a request to obtain an EMM (Entitlement Management Message) to
+ // use to enable processing of ECM(s) (Encryption Management Message).
+ // |init_data| is widevine metadata about the stream needed in the request.
+ // |wrapped_rsa_key| and |signed_license_request| are the device certificate
+ // obtained by HandleDeviceProvisioningResponse.
+ virtual CasStatus GenerateEntitlementRequest(
+ const std::string& init_data, const std::string& device_certificate,
+ const std::string& wrapped_rsa_key, LicenseType license_type,
+ std::string* signed_license_request);
+
+ // Restores a stored license making the keys available for use.
+ virtual CasStatus HandleStoredLicense(const std::string& wrapped_rsa_key,
+ const std::string& license_file);
+
+ // Process a server response containing a EMM for use in the processing of
+ // ECM(s).
+ // If |device_file| is not nullptr and the license policy allows a license to
+ // be stored |device_file| is populated with the bytes of the license secured
+ // for storage.
+ virtual CasStatus HandleEntitlementResponse(
+ const std::string& entitlement_response, std::string* device_file);
+
+ // Process a previously stored device |certificate| and make it available
+ // for use in an EMM request.
+ virtual CasStatus HandleStoredDrmCert(const std::string& certificate,
+ std::string* device_certificate,
+ std::string* wrapped_rsa_key);
+
+ // Generate an entitlement renewal request message in
+ // |signed_renewal_request|.
+ virtual CasStatus GenerateEntitlementRenewalRequest(
+ const std::string& device_certificate,
+ std::string* signed_renewal_request);
+
+ // Process a server response containing a EMM renewal. If |device_file| is not
+ // nullptr and the license policy allows a license renewal to be stored
+ // |device_file| is populated with the bytes of the license secured for
+ // storage.
+ virtual CasStatus HandleEntitlementRenewalResponse(
+ const std::string& renewal_response, std::string* device_file);
+
+ // Query the license to see if a key is usable.
+ virtual bool CanDecryptContent(const KeyId& key_id) const;
+
+ // Update the license after handling license remove. Plugin is disabled to
+ // playback stream, store and renew license.
+ virtual void UpdateLicenseForLicenseRemove();
+
+ // Query the license to see if storage is allowed.
+ virtual bool CanStoreLicense() const;
+
+ // Returns the group id specified in the license. Group id is expected to be
+ // non-empty if the license is MULTI_CONTENT_LICENSE or GROUP_LICENSE; and
+ // empty if the license is SINGLE_CONTENT_LICENSE_DEFAULT.
+ virtual std::string GetGroupId() const;
+
+ // If the license is MULTI_CONTENT_LICENSE, the returned vector contains all
+ // content ids that the license is for. Returns empty if the license if not
+ // MULTI_CONTENT_LICENSE.
+ virtual std::vector GetContentIdList() const;
+
+ // Returns true if the license is MULTI_CONTENT_LICENSE, and false otherwise.
+ virtual bool IsMultiContentLicense() const;
+
+ // Returns true if the license is GROUP_LICENSE, and false otherwise.
+ virtual bool IsGroupLicense() const;
+
+ // Policy timer implentation.
+ void OnTimerEvent() override;
+
+ // Event listener implementation.
+ void OnSessionRenewalNeeded() override;
+
+ void OnSessionKeysChange(const KeyStatusMap& keys_status,
+ bool has_new_usable_key) override;
+
+ void OnExpirationUpdate(int64_t new_expiry_time_seconds) override;
+
+ void OnLicenseExpiration() override;
+
+ void OnNewRenewalServerUrl(const std::string& renewal_server_url) override;
+
+ void OnAgeRestrictionUpdated(const WvCasSessionId& sessionId,
+ uint8_t ecm_age_restriction) override;
+ void OnFingerprintingUpdated(const CasData& fingerprinting) override;
+ void OnServiceBlockingUpdated(const CasData& service_blocking) override;
+
+ void OnSessionFingerprintingUpdated(const WvCasSessionId& sessionId,
+ const CasData& fingerprinting) override;
+
+ void OnSessionServiceBlockingUpdated(
+ const WvCasSessionId& sessionId,
+ const CasData& service_blocking) override;
+
+ void OnEntitlementPeriodUpdateNeeded(
+ const std::string& signed_license_request) override;
+
+ // Query to see if the license is expired.
+ virtual bool IsExpired() const;
+
+ // Notify the license that playback decryption has begun.
+ virtual void BeginDecryption();
+
+ // Returns NoError if a valid entitlement period index exists in
+ // |license_file|. The index will be assigned to |entitlement_period_index|.
+ static CasStatus GetEntitlementPeriodIndexFromStoredLicense(
+ const std::string& license_file, uint32_t& entitlement_period_index);
+
+ CasLicense(const CasLicense&) = delete;
+ CasLicense& operator=(const CasLicense&) = delete;
+
+ private:
+ CasStatus GenerateDeviceProvisioningRequestWithKeybox(
+ std::string* provisioning_request) const;
+ CasStatus GenerateDeviceProvisioningRequestWithOEMCert() const;
+ CasStatus InstallLicense(const std::string& session_key,
+ const std::string& serialized_license,
+ const std::string& core_message,
+ const std::string& signature);
+ CasStatus InstallLicenseRenewal(const std::string& serialized_license,
+ const std::string& core_message,
+ const std::string& signature);
+
+ virtual std::unique_ptr GetPolicyEngine();
+
+ std::unique_ptr policy_engine_;
+ std::shared_ptr crypto_session_;
+ CasEventListener* event_listener_ = nullptr;
+ video_widevine::License license_;
+ std::string emm_request_;
+ std::string emm_response_;
+ std::string renewal_request_;
+ std::string renewal_response_;
+ std::string init_data_;
+ bool is_renewal_in_license_file_ = false;
+};
+
+} // namespace wvcas
+
+#endif // CAS_LICENSE_H
diff --git a/plugin/include/cas_media_id.h b/plugin/include/cas_media_id.h
new file mode 100644
index 0000000..b20bc0d
--- /dev/null
+++ b/plugin/include/cas_media_id.h
@@ -0,0 +1,25 @@
+#ifndef CAS_MEDIA_ID_H
+#define CAS_MEDIA_ID_H
+
+namespace wvcas {
+
+class CasMediaId {
+ protected:
+ CasMediaId() {}
+
+ public:
+ CasMediaId(const CasMediaId&) = delete;
+ CasMediaId& operator=(const CasMediaId&) = delete;
+ virtual ~CasMediaId() {}
+ static std::unique_ptr create();
+ virtual CasStatus initialize(const std::string& init_data) = 0;
+ virtual const std::string content_id() = 0;
+ virtual const std::string provider_id() = 0;
+ virtual bool is_entitlement_rotation_enabled() { return false; }
+ virtual uint32_t entitlement_period_index() = 0;
+ virtual std::string get_init_data() = 0;
+};
+
+} // namespace wvcas
+
+#endif // CAS_MEDIA_ID_H
diff --git a/plugin/include/cas_status.h b/plugin/include/cas_status.h
new file mode 100644
index 0000000..be8ec1a
--- /dev/null
+++ b/plugin/include/cas_status.h
@@ -0,0 +1,53 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine Master
+// License Agreement.
+
+#ifndef CAS_STATUS_H
+#define CAS_STATUS_H
+
+#include
+
+namespace wvcas {
+
+// TODO(jfore): Add more detailed error status codes.
+enum class CasStatusCode : int32_t {
+ kUnknownError = 0,
+ kNoError = 1,
+ kCryptoInterfaceError = 2,
+ kCryptoSessionError = 3,
+ kCasLicenseError = 4,
+ kIndividualizationError = 5,
+ kInvalidParameter = 6,
+ kDecryptionError = 7,
+ kKeyNotFound = 8,
+ kSessionNotFound = 9,
+ kUnknownLicenseType = 10,
+ kLicenseFileParseError = 11,
+ kInvalidLicenseFile = 12,
+ kInvalidPesData = 13,
+ kDeferedEcmProcessing = 14,
+ kAccessDeniedByParentalControl = 15,
+ kUnknownEvent = 16,
+ kOEMCryptoVersionMismatch = 17,
+};
+
+class CasStatus {
+ public:
+ CasStatus(CasStatusCode status = CasStatusCode::kNoError,
+ const std::string& err_string = std::string())
+ : status_(status), err_string_(err_string) {}
+ static CasStatus OkStatus() { return CasStatus(); }
+ virtual ~CasStatus() {}
+
+ virtual CasStatusCode status_code() const { return status_; }
+ virtual const std::string& error_string() const { return err_string_; }
+ virtual bool ok() const { return status_ == CasStatusCode::kNoError; }
+
+ private:
+ CasStatusCode status_;
+ std::string err_string_;
+};
+
+} // namespace wvcas
+
+#endif // CAS_STATUS_H
diff --git a/plugin/include/cas_types.h b/plugin/include/cas_types.h
new file mode 100644
index 0000000..bfa5370
--- /dev/null
+++ b/plugin/include/cas_types.h
@@ -0,0 +1,116 @@
+// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
+// source code may only be used and distributed under the Widevine Master
+// License Agreement.
+
+#ifndef CAS_TYPES_H
+#define CAS_TYPES_H
+
+#include