/*******************************************************************************
 *
 * Reference APIs needed to support Widevine's crypto algorithms.
 *
 ******************************************************************************/

#ifndef _OEMCRYPTO_AES_H
#define _OEMCRYPTO_AES_H

typedef	unsigned char	OEMCrypto_UINT8;
typedef char		OEMCrypto_INT8;
typedef	unsigned int	OEMCrypto_UINT32;
typedef	unsigned int	OEMCrypto_SECURE_BUFFER;


typedef enum OEMCryptoResult {
  OEMCrypto_SUCCESS = 0,
  OEMCrypto_ERROR_INIT_FAILED,
  OEMCrypto_ERROR_TERMINATE_FAILED,
  OEMCrypto_ERROR_ENTER_SECURE_PLAYBACK_FAILED,
  OEMCrypto_ERROR_EXIT_SECURE_PLAYBACK_FAILED,
  OEMCrypto_ERROR_SHORT_BUFFER,
  OEMCrypto_ERROR_NO_DEVICE_KEY,
  OEMCrypto_ERROR_NO_ASSET_KEY,
  OEMCrypto_ERROR_KEYBOX_INVALID,
  OEMCrypto_ERROR_NO_KEYDATA,
  OEMCrypto_ERROR_NO_CW,
  OEMCrypto_ERROR_DECRYPT_FAILED,
  OEMCrypto_ERROR_WRITE_KEYBOX,
  OEMCrypto_ERROR_WRAP_KEYBOX,
  OEMCrypto_ERROR_BAD_MAGIC,
  OEMCrypto_ERROR_BAD_CRC,
  OEMCrypto_ERROR_NO_DEVICEID,
  OEMCrypto_ERROR_RNG_FAILED,
  OEMCrypto_ERROR_RNG_NOT_SUPPORTED,
  OEMCrypto_ERROR_SETUP
} OEMCryptoResult;


#ifdef __cplusplus
extern "C" {
#endif

#define OEMCrypto_Initialize _oec01
#define OEMCrypto_Terminate _oec02
#define OEMCrypto_SetEntitlementKey _oec03
#define OEMCrypto_DeriveControlWord _oec04
#define OEMCrypto_DecryptVideo _oec05
#define OEMCrypto_DecryptAudio _oec06
#define OEMCrypto_InstallKeybox _oec07
#define OEMCrypto_GetKeyData _oec08
#define OEMCrypto_IsKeyboxValid _oec09
#define OEMCrypto_GetRandom _oec10
#define OEMCrypto_GetDeviceID _oec11
#define OEMCrypto_EnterSecurePlayback _oec12
#define OEMCrypto_ExitSecurePlayback _oec13
#define OEMCrypto_WrapKeybox _oec14

/*
 * OEMCrypto_Initialize
 *
 * Description:
 *   Initializes the crypto hardware
 *
 * Parameters:
 *   N/A
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
 */
OEMCryptoResult OEMCrypto_Initialize(void);


/*
 * OEMCrypto_Terminate
 *
 * Description:
 *   The API closes the crypto operation and releases all resources used.
 *
 * Parameters:
 *   N/A
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_TERMINATE_FAILED failed to de-initialize crypto hardware
 */
OEMCryptoResult OEMCrypto_Terminate(void);

/*
 * OEMCrypto_EnterSecurePlayback
 *
 * Description:
 *   Configures the security processor for secure decryption.  This may involve
 *   setting up firewall regions.  It is called when the decrypt session for an
 *   asset is established.
 *
 * Parameters:
 *   N/A
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_ENTER_SECURE_PLAYBACK_FAILED
 */
OEMCryptoResult OEMCrypto_EnterSecurePlayback(void);

/*
 * OEMCrypto_ExitSecurePlayback
 *
 * Description:
 *   Exit the secure playback mode.  This may involve releasing the firewall regions.  It is
 *   called when the decrypt session for an asset is closed.
 *
 * Parameters:
 *   N/A
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_EXIT_SECURE_PLAYBACK_FAILED
 */
OEMCryptoResult OEMCrypto_ExitSecurePlayback(void);

/*
 * OEMCrypto_SetEntitlementKey
 *
 * Description:
 *   Decrypt the entitlement (EMM) key, also known as the asset key,
 *   using the encrypted device key (Device Key field) in the Widevine Keybox.
 *
 *   As shown in Figure 1 on the next page, Step 1 uses an OEM root key to decrypt
 *   (AES-128-ECB) the Device Key in the Keybox; the result is “latched” in hardware
 *   key ladder.
 *
 *   Step 2 uses the “latched” clear device key to decrypt (AES-128-ECB) the
 *   entitlement key passed in as the *emmKey parameter and “latched” the clear
 *   entitlement key in hardware for the next operation.
 *
 * Parameters:
 *    emmKey (in) - pointer to the encrypted entitlement key
 *    emmKeyLength (in) – length of entitlement key in bytes
 *
 * Returns:
 *    OEMCrypto_SUCCESS success
 *    OEMCrypto_ERROR_NO_DEVICE_KEY failed to decrypt device key
 *    OEMCrypto_ERROR_NO_ASSET_KEY  failed to decrypt asset key
 *    OEMCrypto_ERROR_KEYBOX_INVALID cannot decrypt and read from Keybox
 */

OEMCryptoResult OEMCrypto_SetEntitlementKey(const OEMCrypto_UINT8* emmKey,
                                            const OEMCrypto_UINT32 emmKeyLength);

/*
 * OEMCrypto_DeriveControlWord
 *
 * Description:
 *   Using the active key ladder key from OEMCrypto_SetEntitlementKey(), decrypts
 *   (AES-128-CBC, iv=0) the 32-byte ECM referenced by the *ecm parameter; returns in
 *   *flags the first clear 4 bytes data. “Latched” the clear bytes [4..20] as the
 *   clear control word for subsequent payload decryption operation.
 *
 * Parameters:
 *   ecm (in) - points to encrypted ECM data
 *   length (in) – length of encrypted ECM data in bytes
 *   flags (out) - points to buffer to receive 4 byte clear flag value
 *
 *  Returns:
 *    OEMCrypto_SUCCESS success
 *    OEMCrypto_ERROR_NO_CW cannot decrypt control word
*/

OEMCryptoResult OEMCrypto_DeriveControlWord(const OEMCrypto_UINT8* ecm,
                                            const OEMCrypto_UINT32 length,
                                            OEMCrypto_UINT32* flags);


/*
 * OEMCrypto_DecryptVideo
 *
 * Description:
 *
 * The API decrypts (AES-128-CBC) the video payload in the buffer referenced by
 * the *input parameter into the secure buffer referenced by the output
 * parameter, using the control word “latched” in the active hardware key
 * ladder. If inputLength is not a multiple of the crypto block size (16 bytes),
 * the API handles the residual bytes using CipherText Stealing (CTS).
 *
 * Parameters:
 *   iv (in/out) - If iv is NULL, then no decryption is required, i.e. the packets are
 *                 already clear.  Otherwise, iv references the AES initialization
 *                 vector. Note that the updated IV  after processing the final crypto
 *                 block must be passed back out in *iv.
 *   input (in) - buffer containing the encrypted data
 *   inputLength (in) - number of bytes in the input payload, which may not be a multiple of 16 bytes
 *   output (in) – reference to the secure buffer which will receive the decrypted data
 *   outputLength (out) - number of bytes written into the secure buffer
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_DECRYPT_FAILED failed decryption
*/

OEMCryptoResult
OEMCrypto_DecryptVideo(const OEMCrypto_UINT8* iv,
                       const OEMCrypto_UINT8* input, const OEMCrypto_UINT32 inputLength,
                       OEMCrypto_UINT32 output_handle, OEMCrypto_UINT32 output_offset, OEMCrypto_UINT32 *outputLength);


/*
 * OEMCrypto_DecryptAudio
 *
 * Description:
 *   The API decrypts (AES-128-CBC) the audio payload in the buffer referenced by
 *   the *input parameter into the non-secure buffer referenced by the output
 *   parameter, using the control word “latched” in the active hardware key
 *   ladder. If inputLength is not a multiple of the crypto block size (16 bytes),
 *   the API handles the residual bytes using CipherText Stealing (CTS).
 *
 *   OEMCrypto_DecryptAudio must make sure that it cannot be used to decrypt a video
 *   stream into non-firewalled buffers, by verifying that no video packets are
 *   processed.
 *
 * Parameters:
 *   iv (in/out) - If iv is NULL, then no decryption is required, i.e. the packets are
 *                 already clear.  Otherwise, iv references the AES initialization
 *                 vector. Note that the updated IV  after processing the final crypto
 *                 block must be passed back out in *iv.
 *   input (in) - buffer containing the encrypted data
 *   inputLength (in) - number of bytes in the input payload, which may not be a multiple of 16 bytes
 *   output (in) – reference to the non-secure buffer which will receive the decrypted data
 *   outputLength (out) - number of bytes written into the non-secure buffer
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_DECRYPT_FAILED failed decryption
*/
OEMCryptoResult
OEMCrypto_DecryptAudio(const OEMCrypto_UINT8* iv,
                       const OEMCrypto_UINT8* input, const OEMCrypto_UINT32 inputLength,
                       OEMCrypto_UINT8 *output, OEMCrypto_UINT32 *outputLength);


/*
 * OEMCrypto_InstallKeybox
 *
 * Description:
 *   Unwrap and store the keybox to persistent memory. The device key must be stored
 *   securely. The device key will be decrypted and
 *   “latched” into hardware key ladder by OEMCrypto_SetEntitlementKey.
 *
 *   This function is used once to load the keybox onto the device at provisioning time.
 *
 * Parameters:
 *   keybox (in) - Pointer to clear keybox data.  Must have been wrapped with OEMCrypto_WrapKeybox
 *   keyboxLength (in) - Length of the keybox data in bytes
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_WRITE_KEYBOX failed to handle and store Keybox
 */

OEMCryptoResult OEMCrypto_InstallKeybox(OEMCrypto_UINT8 *keybox,
                                        OEMCrypto_UINT32 keyBoxLength);


/*
 * OEMCrypto_IsKeyboxValid
 *
 * Description:
 *   Validate the Widevine Keybox stored on the device.
 *
 * The API performs two verification steps on the Keybox. It first verifies the MAGIC
 * field contains a valid signature (i.e. ‘k’’b’’o’’x’). The API then computes the
 * CRC using CRC-32-IEEE 802.3 standard and compares the checksum to the CRC stored
 * in the Keybox. The CRC is computed over the entire Keybox excluding the 4 bytes
 * CRC (i.e. Keybox[0..123].
 *
 * Parameters:
 *   none
 *
 * Returns:
 *   OEMCrypto_SUCCESS
 *   OEMCrypto_ERROR_BAD_MAGIC
 *   OEMCrypto_ERROR_BAD_CRC
 */

OEMCryptoResult OEMCrypto_IsKeyboxValid(void);


/*
 * OEMCrypto_GetDeviceID
 *
 * Description:
 *   Retrieve the device's unique identifier from the Keybox.
 *
 * Parameters:
 *   deviceId (out) - pointer to the buffer that receives the Device ID
 *   idLength (in/out) - on input, size of the caller's device ID buffer.
 *        On output, the number of bytes written into the buffer.
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return the device ID
 *   OEMCrypto_ERROR_NO_DEVICEID failed to return Device Id
 */
OEMCryptoResult OEMCrypto_GetDeviceID(OEMCrypto_UINT8* deviceID,
                                      OEMCrypto_UINT32 *idLength);


/*
 * OEMCrypto_GetKeyData
 *
 * Description:
 *   Returns the Key Data field from the Keybox. The Key Data field does not need to be
 *   encrypted by an OEM root key, but may be if desired.
 *
 *   If the Key Data field was encrypted with an OEM root key when the Keybox was stored
 *   on the device, then this function should decrypt it and return the clear Key Data.
 *   If the Key Data was not encrypted, then this function should just access and return
 *   the clear Key data.
 *
 * Parameters:
 *   keyData (out) - pointer to the buffer to hold the Key Data field from the Keybox
 *   dataLength (in/out) - on input, the allocated buffer size.  On output, the number
 *       of bytes in KeyData.
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return the KeyData
 *   OEMCrypto_ERROR_NO_KEYDATA failed to return KeyData
 */
OEMCryptoResult OEMCrypto_GetKeyData(OEMCrypto_UINT8* keyData,
                                     OEMCrypto_UINT32 *keyDataLength);


/*
 * OEMCrypto_GetRandom
 *
 * Description:
 *   Returns a buffer filled with hardware-generated random bytes, if supported by the hardware.
 *
 * Parameters:
 *   randomData (out) - Points to the buffer that should recieve the random data.
 *   dataLength (in)  - Length of the random data buffer in bytes.
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_RNG_FAILED failed to generate random number
 *   OEMCrypto_ERROR_RNG_NOT_SUPPORTED function not supported
 */

OEMCryptoResult OEMCrypto_GetRandom(OEMCrypto_UINT8* randomData,
                                    OEMCrypto_UINT32 dataLength);

/*
 * OEMCrypto_WrapKeybox
 *
 * Description:
 *   Wrap the Keybox with a key derived for the device key.
 *
 * Parameters:
 *   keybox (in) - Pointer to keybox data.
 *   keyboxLength - Length of the Keybox data in bytes
 *   wrappedKeybox (out) - Pointer to wrapped keybox
 *   wrappedKeyboxLength (out) - Pointer to the length of the wrapped keybox in bytes
 *   transportKey (in) - An optional AES transport key. If provided, the parameter
 *                       keybox is passed encrypted with this transport key with AES-CBC
 *                       and a null IV
 *   transportKeyLength - number of bytes in the transportKey
 *
 * Returns:
 *   OEMCrypto_SUCCESS success
 *   OEMCrypto_ERROR_WRAP_KEYBOX failed to wrap Keybox
 */

OEMCryptoResult OEMCrypto_WrapKeybox(OEMCrypto_UINT8 *keybox,
                                     OEMCrypto_UINT32 keyBoxLength,
                                     OEMCrypto_UINT8 *wrappedKeybox,
                                     OEMCrypto_UINT32 *wrappedKeyBoxLength,
                                     OEMCrypto_UINT8 *transportKey,
                                     OEMCrypto_UINT32 transportKeyLength);

#ifdef __cplusplus
}
#endif

#endif

/***************************** End of File *****************************/