// 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. * * * ![Generic Encrypt and Decrypt flow](fig2.svg) * * ![Generic Sign flow](fig3.svg) * * ![Generic Verify flow](fig4.svg) * * @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 } 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_V18 _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_V18 _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_V18 _oecc95 #define OEMCrypto_PrepAndSignLicenseRequest _oecc96 #define OEMCrypto_PrepAndSignRenewalRequest _oecc97 #define OEMCrypto_PrepAndSignProvisioningRequest _oecc98 #define OEMCrypto_LoadLicense_V18 _oecc99 #define OEMCrypto_LoadRenewal _oecc101 #define OEMCrypto_LoadProvisioning_V18 _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_SetDecryptHash _oecc143 #define OEMCrypto_LoadLicense _oecc144 #define OEMCrypto_LoadProvisioning _oecc145 #define OEMCrypto_LoadProvisioningCast _oecc146 #define OEMCrypto_PrepAndSignLicenseRelease _oecc147 #define OEMCrypto_GetUsageEntryInfo _oecc148 // 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 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. * * 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. * * Starting in OEMCrypto v19, the |message| buffer must be hashed using SHA512 * before signing. * * 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 17. */ 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); /** * This function replaces both OEMCrypto_DeactivateUsageEntry and * OEMCrypto_ReportUsage. As with other OEMCrypto_PrepAndSign* functions, it * first verifies that the core_message_size is the right size. If not, it * returns OEMCrypto_ERROR_SHORT_BUFFER. * OEMCrypto will change the status of the usage entry to InactiveUsed if it was * Active, or InactiveUnused if it was Unused. This also increments the entry's * generation number by 2, 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. * * OEMCrypto will use ODK_PrepareCoreLicenseRelease 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_PrepareCoreLicenseRelease is described in the document "Widevine Core * Message Serialization". * * This function generates a HMAC-SHA256 signature using the mac_key[client] * for license release 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(). * * 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_NOT_IMPLEMENTED since OEMCrypto does not implement * license release before v19 * @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 * * @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 is new in API version 19. */ OEMCryptoResult OEMCrypto_PrepAndSignLicenseRelease( 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 should generate three secondary keys, mac_key[server], * mac_key[client], and encryption_key, for handling signing and content key * derivation under the license server protocol for CENC. * * Then 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. * * 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] context: pointer to memory containing context data. * @param[in] context_length: length of the context, in bytes. * @param[in] derivation_key: pointer to memory containing derivation key. * @param[in] derivation_key_length: length of the derivation_key, in bytes. * @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 * @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 * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * @retval OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED * * @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* context, size_t context_length, const uint8_t* derivation_key, size_t derivation_key_length, 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 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: * * ![Drawing of block offset](fig5.svg) * * 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: * * ![CBCS Scheme](fig6.svg) * * 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: * * ![CBCS Scheme - final partial block](fig7.svg) * * 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. * * ![CTR Mode - no skip pattern](fig8.svg) * * 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. * * ![CTR Mode - with skip pattern](fig9.svg) * * @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 Operation](fig1.svg) * * 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. * * ![InstallKeyboxOrOEMCert](fig10.svg) * * @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(). * * * @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 a strong * encryption key and signing key algorithm. * * 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 use the provisioning request to derive * mac_key[server] and verify the signature of the message using HMAC-SHA256. * 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. * * 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]). * 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] provision_request: the initial provisioning request. * @param[in] provision_request_length: length of provision_request, in bytes. * @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* provision_request, size_t provision_request_length, 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); /** * Load and parse a provisioning response, and then rewrap the private key. We * recommend that the OEM use a strong encryption key and signing key algorithm. * * This is the same as OEMCrypto_LoadProvisioning except it is for CAST devices. * This should return OEMCrypto_ERROR_NOT_IMPLEMENTED for non-CAST devices. * * @param[in] session: crypto session identifier. * @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] provision_request: the initial provisioning request. * @param[in] provision_request_length: length of provision_request, in bytes. * @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 * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED * * @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 was added in API version 19. */ OEMCryptoResult OEMCrypto_LoadProvisioningCast( OEMCrypto_SESSION session, const uint8_t* derivation_key, size_t derivation_key_length, const uint8_t* provision_request, size_t provision_request_length, 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_LoadLicense(). 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_LoadLicense() * * @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 using the message. * * 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. * * ![Usage Report Timeline](fig11.svg) * * 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. * * ![Secure Clock versus Secure Timer versus Insecure Clock](fig12.svg) * * 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); /** * Fetches information from a license release without performing any signatures * or deactivating the license. * * @param[in] session: handle for the session to be used. * @param[out] status: the enumeration of OEMCrypto_Usage_Entry_Status. * @param[out] seconds_since_license_received: the time since the license being * requested in seconds. * @param[out] seconds_since_first_decrypt: the time since playback has * started in seconds. * * @retval OEMCrypto_SUCCESS success * @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 * * @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 19. */ OEMCryptoResult OEMCrypto_GetUsageEntryInfo( OEMCrypto_SESSION session, OEMCrypto_Usage_Entry_Status* status, int64_t* seconds_since_license_received, int64_t* seconds_since_first_decrypt); /** * 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 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] crc32: CRC of previously decrypted frame. * * @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, uint32_t crc32); /** * 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_SetDecryptHash * @deprecated * Not required for the current version of OEMCrypto. Declared here to * help with backward compatibility. */ OEMCryptoResult OEMCrypto_SetDecryptHash_V18(OEMCrypto_SESSION session, uint32_t frame_number, const uint8_t* hash, size_t hash_length); /* * 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); /** * OEMCrypto_GenerateDerivedKeys_V18 * @deprecated * Not required for the current version of OEMCrypto. Declared here to * help with backward compatibility. */ OEMCryptoResult OEMCrypto_GenerateDerivedKeys_V18( 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); /** * OEMCrypto_DeriveKeysFromSessionKey_V18 * @deprecated * Not required for the current version of OEMCrypto. Declared here to * help with backward compatibility. */ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey_V18( 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); /** * OEMCrypto_LoadLicense_V18 * @deprecated * Not required for the current version of OEMCrypto. Declared here to * help with backward compatibility. */ OEMCryptoResult OEMCrypto_LoadLicense_V18(OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, size_t core_message_length, const uint8_t* signature, size_t signature_length); /** * OEMCrypto_LoadProvisioning_V18 * @deprecated * Not required for the current version of OEMCrypto. Declared here to * help with backward compatibility. */ OEMCryptoResult OEMCrypto_LoadProvisioning_V18( 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); /****************************************************************************/ /****************************************************************************/ #ifdef __cplusplus } #endif #endif // OEMCRYPTO_CENC_H_