diff --git a/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC_v14.pdf b/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC_v14.pdf new file mode 100644 index 00000000..543b4b15 Binary files /dev/null and b/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC_v14.pdf differ diff --git a/libwvdrmengine/docs/Widevine_Modular_DRM_Version_14_Delta.pdf b/libwvdrmengine/docs/Widevine_Modular_DRM_Version_14_Delta.pdf new file mode 100644 index 00000000..82151ee1 Binary files /dev/null and b/libwvdrmengine/docs/Widevine_Modular_DRM_Version_14_Delta.pdf differ diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index 525e93ff..96d1bf35 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -6,9 +6,9 @@ * Reference APIs needed to support Widevine's crypto algorithms. * * See the document "WV Modular DRM Security Integration Guide for Common - * Encryption (CENC) -- version 13" for a description of this API. You + * Encryption (CENC) -- version 14" for a description of this API. You * can find this document in the widevine repository as - * docs/WidevineModularDRMSecurityIntegrationGuideforCENC_v13.pdf + * docs/WidevineModularDRMSecurityIntegrationGuideforCENC_v14.pdf * Changes between different versions of this API are documented in the files * docs/Widevine_Modular_DRM_Version_*_Delta.pdf * @@ -79,6 +79,8 @@ typedef enum OEMCryptoResult { OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE = 48, OEMCrypto_ERROR_ENTRY_IN_USE = 49, OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50, // Reserved. Do not use. + OEMCrypto_KEY_NOT_LOADED = 51, + OEMCrypto_KEY_NOT_ENTITLED = 52, } OEMCryptoResult; /* @@ -144,7 +146,7 @@ typedef struct { } buffer; } OEMCrypto_DestBufferDesc; -/** OEMCryptoCipherMode is used in LoadKeys to prepare a key for either CTR +/** OEMCryptoCipherMode is used in SelectKey to prepare a key for either CTR * decryption or CBC decryption. */ typedef enum OEMCryptoCipherMode { @@ -152,6 +154,14 @@ typedef enum OEMCryptoCipherMode { OEMCrypto_CipherMode_CBC, } OEMCryptoCipherMode; +/** OEMCrypto_LicenseType is used in LoadKeys to indicate if the key objects + * are for content keys, or for entitlement keys. + */ +typedef enum OEMCrypto_LicenseType { + OEMCrypto_ContentLicense = 0, + OEMCrypto_EntitlementLicense = 1 +} OEMCrypto_LicenseType; + /* * OEMCrypto_KeyObject * Points to the relevant fields for a content key. The fields are extracted @@ -170,8 +180,6 @@ typedef enum OEMCryptoCipherMode { * key_control field. * key_control - the key control block. It is encrypted (AES-128-CBC) with * the content key from the key_data field. - * cipher_mode - whether the key should be prepared for CTR mode or CBC mode - * when used in later calls to DecryptCENC. * * The memory for the OEMCrypto_KeyObject fields is allocated and freed * by the caller of OEMCrypto_LoadKeys(). @@ -184,9 +192,31 @@ typedef struct { size_t key_data_length; const uint8_t* key_control_iv; const uint8_t* key_control; - OEMCryptoCipherMode cipher_mode; } OEMCrypto_KeyObject; +/* + * OEMCrypto_EntitledContentKeyObject + * 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. + * entitlement_key_id - entitlement key id to be matched to key table. + * entitlement_key_id_length - length of entitlment_key_id in bytes (1 to 16). + * content_key_id - content key id to be loaded into key table. + * content_key_id_length - length of content key id in bytes (1 to 16). + * key_data_iv - the IV for performing AES-256-CBC decryption of the key data. + * key_data - encrypted content key data. + * key_data_length - length of key_data - 16 or 32 depending on intended use. + */ +typedef struct { + const uint8_t* entitlement_key_id; + size_t entitlement_key_id_length; + const uint8_t* content_key_id; + size_t content_key_id_length; + const uint8_t* content_key_data_iv; + const uint8_t* content_key_data; + size_t content_key_data_length; +} OEMCrypto_EntitledContentKeyObject; + /* * OEMCrypto_KeyRefreshObject * Points to the relevant fields for renewing a content key. The fields are @@ -323,6 +353,16 @@ typedef enum OEMCrypto_ProvisioningMethod { #define OEMCrypto_Hash_Not_Supported 0 #define OEMCrypto_HMAC_Clear_Buffer 1 +/* + * 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. */ @@ -342,7 +382,7 @@ typedef enum OEMCrypto_ProvisioningMethod { #define OEMCrypto_GenerateNonce _oecc14 #define OEMCrypto_LoadKeys_V8 _oecc15 #define OEMCrypto_RefreshKeys _oecc16 -#define OEMCrypto_SelectKey _oecc17 +#define OEMCrypto_SelectKey_V13 _oecc17 #define OEMCrypto_RewrapDeviceRSAKey _oecc18 #define OEMCrypto_LoadDeviceRSAKey _oecc19 #define OEMCrypto_GenerateRSASignature_V8 _oecc20 @@ -367,7 +407,7 @@ typedef enum OEMCrypto_ProvisioningMethod { #define OEMCrypto_IsAntiRollbackHwPresent _oecc39 #define OEMCrypto_CopyBuffer _oecc40 #define OEMCrypto_QueryKeyControl _oecc41 -#define OEMCrypto_LoadTestKeybox _oecc42 +#define OEMCrypto_LoadTestKeybox_V13 _oecc42 #define OEMCrypto_ForceDeleteUsageEntry _oecc43 #define OEMCrypto_GetHDCPCapability _oecc44 #define OEMCrypto_LoadTestRSAKey _oecc45 @@ -381,7 +421,7 @@ typedef enum OEMCrypto_ProvisioningMethod { #define OEMCrypto_IsSRMUpdateSupported _oecc53 #define OEMCrypto_GetCurrentSRMVersion _oecc54 #define OEMCrypto_LoadSRM _oecc55 -#define OEMCrypto_LoadKeys _oecc56 +#define OEMCrypto_LoadKeys_v13 _oecc56 #define OEMCrypto_RemoveSRM _oecc57 #define OEMCrypto_CreateUsageTableHeader _oecc61 #define OEMCrypto_LoadUsageTableHeader _oecc62 @@ -393,7 +433,11 @@ typedef enum OEMCrypto_ProvisioningMethod { #define OEMCrypto_MoveEntry _oecc68 #define OEMCrypto_CopyOldUsageEntry _oecc69 #define OEMCrypto_CreateOldUsageEntry _oecc70 - +#define OEMCrypto_GetAnalogOutputFlags _oecc71 +#define OEMCrypto_LoadTestKeybox _oecc78 +#define OEMCrypto_LoadEntitledContentKeys _oecc79 +#define OEMCrypto_SelectKey _oecc81 +#define OEMCrypto_LoadKeys _oecc82 /* * OEMCrypto_Initialize @@ -694,6 +738,17 @@ OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, * Refer to document "Widevine Modular DRM Security Integration Guide for * CENC" for details. * + * If the parameter 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 parameter 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. * @@ -804,6 +859,11 @@ OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, * key_array (in) - set of keys to be installed. * pst (in) - the Provider Session Token. * pst_length (in) - the length of pst. + * srm_restriction_data (in) - optional data specifying the minimum SRM + * version. + * license_type (in) - specifies if the license contains content keys or + * entitlement keys. + * * Threading: * This function may be called simultaneously with functions on other @@ -826,14 +886,75 @@ OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session, * larger than the supported size. * * Version: - * This method changed in API version 11. + * This method changed in API version 14. */ OEMCryptoResult OEMCrypto_LoadKeys( OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, const uint8_t* signature, size_t signature_length, const uint8_t* enc_mac_keys_iv, const uint8_t* enc_mac_keys, size_t num_keys, const OEMCrypto_KeyObject* key_array, const uint8_t* pst, - size_t pst_length, const uint8_t* srm_requirement); + size_t pst_length, const uint8_t* srm_requirement, + OEMCrypto_LicenseType license_type); + + +/* + * OEMCrypto_LoadEntitledContentKeys + * + * Description: + * Load content keys into a session which already has entitlement + * keys loaded. This function will only be called for a session after a call + * to OEMCrypto_LoadKeys with the parameter type license_type equal to + * OEMCrypto_EntitlementLicense. This function may be called multiple times + * for the same session. + * + * If the session does not have license_type equal to + * OEMCrypto_EntitlementLicense, 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 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, and 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. + * + * 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 appropriate to + * store the encrypted content key data in the key table, and defer decrypting + * it until the function SelectKey is called. + * + * Parameters: + * session (in) - handle for the session to be used. + * num_keys (in) - number of keys present. + * key_array (in) - set of key updates. + * + * Returns + * OEMCrypto_SUCCESS success + * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INVALID_CONTEXT + * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES + * OEMCrypto_ERROR_UNKNOWN_FAILURE + * OEMCrypto_KEY_NOT_ENTITLED + * Threading + * + * This function may be called simultaneously with functions on other + * sessions, but not with other functions on this session. + * + * Version + * This method is new in API version 14. + */ +OEMCryptoResult OEMCrypto_LoadEntitledContentKeys( + OEMCrypto_SESSION session, + size_t num_keys, + const OEMCrypto_EntitledContentKeyObject* key_array); /* * OEMCrypto_RefreshKeys @@ -872,6 +993,19 @@ OEMCryptoResult OEMCrypto_LoadKeys( * this case, key_control_iv will also be null and the control block will not * be encrypted. * + * If the session's license_type is OEMCrypto_ContentLicense, and the + * KeyRefreshObject's key_id is not null, then the entry in the + * keytable with the matching content_key_id is updated. + * + * If the session's license_type is OEMCrypto_EntitlementLicense, and the + * KeyRefreshObject's key_id is not null, then the entry in the keytable with + * the matching entitlment_key_id is updated. + * + * If the key_id is not null, and no matching entry is found in the key + * table, then return OEMCrypto_KEY_NOT_LOADED. + * + * Aside from the key's duration, no other values in the key control block + * should be updated by this function. * * Verification: * The following checks should be performed. If any check fails, an error is @@ -920,6 +1054,7 @@ OEMCryptoResult OEMCrypto_LoadKeys( * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_BUFFER_TOO_LARGE + * OEMCrypto_KEY_NOT_LOADED * * Buffer Sizes * OEMCrypto shall support message sizes of at least 8 KiB. @@ -964,8 +1099,8 @@ OEMCryptoResult OEMCrypto_RefreshKeys( * OEMCrypto_ERROR_NO_CONTENT_KEY. * * Parameters - * key_id (in) - The unique id of the key of interest. - * key_id_length (in) - The length of key_id, in bytes. From 1 to 16 + * content_key_id (in) - The unique id of the content key of interest. + * content_key_id_length (in) - The length of key_id, in bytes. From 1 to 16 * inclusive. * key_control_block(out) - A caller-owned buffer. * key_control_block_length (in/out) - The length of key_control_block buffer. @@ -991,8 +1126,8 @@ OEMCryptoResult OEMCrypto_RefreshKeys( * This method is added in API version 10. */ OEMCryptoResult OEMCrypto_QueryKeyControl(OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length, + const uint8_t* content_key_id, + size_t content_key_id_length, uint8_t* key_control_block, size_t* key_control_block_length); @@ -1018,36 +1153,49 @@ OEMCryptoResult OEMCrypto_QueryKeyControl(OEMCrypto_SESSION session, * Step 3: use the latched content key to decrypt (AES-128-CTR) 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. Continue to use this key until OEMCrypto_SelectKey() is - * called again, or until OEMCrypto_CloseSession() is called. + * OEMCrypto_Generic_Verify as specified in the key control block. + * If the key will be used with OEMCrypto_Generic_Encrypt or + * OEMCrypto_Generic_Decrypt, the cipher mode will always be + * OEMCrypto_CipherMode_CBC. Continue to use this key until + * OEMCrypto_SelectKey() is called again, or until + * OEMCrypto_CloseSession() is called. * * Verification: * The following checks should be performed if is_encrypted is true. If any * check fails, an error is returned, and no decryption is performed. * - * 1. If the current key's control block has a nonzero Duration field, then + * 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_KEY_NOT_LOADED. + * + * 2. If the current 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 may return * OEMCrypto_ERROR_KEY_EXPIRED from OEMCrypto_SelectKey, or SelectKey may * return success from select key and the decrypt or generic crypto call will * return OEMCrypto_ERROR_KEY_EXPIRED. - * 2. If the key control block has the bit Disable_Analog_Output set, then + * + * 3. 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 * output that cannot be disabled, then the key is not selected, and * OEMCrypto_ERROR_ANALOG_OUTPUT is returned. - * 3. If the key control block has HDCP required, and the device cannot + * + * 4. 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. - * 4. If the key control block has a nonzero value for HDCP_Version, and the + * + * 5. 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. * * Parameters: * session (in) - crypto session identifier - * key_id (in) - pointer to the Key ID - * key_id_length (in) - length of the Key ID in bytes. From 1 to 16 + * content_key_id (in) - pointer to the Content Key ID + * content_key_id_length (in) - length of the Key ID in bytes. From 1 to 16 * inclusive. + * cipher_mode (in) - 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. * * Threading: * This function may be called simultaneously with functions on other @@ -1066,13 +1214,15 @@ OEMCryptoResult OEMCrypto_QueryKeyControl(OEMCrypto_SESSION session, * OEMCrypto_ERROR_KEY_EXPIRED * OEMCrypto_ERROR_ANALOG_OUTPUT * OEMCrypto_ERROR_INSUFFICIENT_HDCP + * OEMCrypto_KEY_NOT_LOADED * * Version: - * This method changed in API version 8. + * This method changed in API version 14. */ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length); + const uint8_t* content_key_id, + size_t content_key_id_length, + OEMCryptoCipherMode cipher_mode); /* * OEMCrypto_DecryptCENC @@ -1132,7 +1282,7 @@ OEMCryptoResult OEMCrypto_SelectKey(OEMCrypto_SESSION session, * change the status to "active" and set the time_of_first_decrypt. * * The decryption mode, either OEMCrypto_CipherMode_CTR or - * OEMCrypto_CipherMode_CBC, was specified in the call to OEMCrypto_LoadKeys. + * OEMCrypto_CipherMode_CBC, was specified in the call to OEMCrypto_SelectKey. * The encryption pattern is specified by the fields in the parameter * pattern. A description of partial encryption patterns can be found in the * document Draft International Standard ISO/IEC DIS 23001-7. Search for the @@ -1502,7 +1652,8 @@ OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(OEMCrypto_SESSION session, * The test keybox can be found in the reference implementation. * * Parameters - * none + * buffer (in) - pointer to memory containing test keybox, in binary form. + * length (in) - length of the buffer, in bytes. * * Returns * OEMCrypto_SUCCESS success @@ -1515,7 +1666,7 @@ OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(OEMCrypto_SESSION session, * Version * This method is added in API version 10. */ -OEMCryptoResult OEMCrypto_LoadTestKeybox(); +OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t *buffer, size_t length); /* * OEMCrypto_IsKeyboxValid @@ -1709,7 +1860,9 @@ OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength); * * Parameters: * session (in) - crypto session identifier. - * unaligned_nonce (in) - The nonce provided in the provisioning response. + * unaligned_nonce (in) - The nonce provided in the provisioning + * - response. This points to an uint32_t that might + * - not be aligned to a word boundary. * encrypted_message_key (in) - message_key encrypted by private key * - from OEM cert. * encrypted_message_key_length (in) - length of encrypted_message_key in @@ -1842,7 +1995,9 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30( * - signature for message, received from the * - provisioning server. * signature_length (in) - length of the signature, in bytes. - * unaligned_nonce (in) - The nonce provided in the provisioning response. + * unaligned_nonce (in) - The nonce provided in the provisioning + * - response. This points to an uint32_t that might + * - not be aligned to a word boundary. * enc_rsa_key (in) - Encrypted device private RSA key received from * - the provisioning server. Format is PKCS#8 * - binary DER encoded, encrypted with the derived @@ -2329,8 +2484,13 @@ OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* max); * High end devices should also support 3072 bit RSA keys. Devices that are * cast receivers should also support RSA cast receiver certificates. * - * Parameters: - * none + * 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. OEMCrypto should not reject such + * keys. + * + * Parameters: none * * Threading: * This function may be called simultaneously with any other functions. @@ -2521,6 +2681,7 @@ OEMCryptoResult OEMCrypto_Generic_Decrypt( * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_BUFFER_TOO_LARGE + * OEMCrypto_ERROR_NOT_IMPLEMENTED * * Buffer Sizes * OEMCrypto shall support buffer sizes of at least 100 KiB for generic @@ -2586,6 +2747,7 @@ OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES * OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_BUFFER_TOO_LARGE + * OEMCrypto_ERROR_NOT_IMPLEMENTED * * Buffer Sizes * OEMCrypto shall support buffer sizes of at least 100 KiB for generic @@ -3261,6 +3423,38 @@ OEMCryptoResult OEMCrypto_CopyOldUsageEntry(OEMCrypto_SESSION session, const uint8_t*pst, size_t pst_length); +/* + * OEMCrypto_GetAnalogOutputFlags + * + * Description: + * 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. + * + * Parameters: + * none. + * + * Threading: + * This function will not be called simultaneously with any session functions. + * + * Returns: + * Returns a bitwise OR of the following flags. + * 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 + * + * Version: + * This method is new in API version 14. + */ +uint32_t OEMCrypto_GetAnalogOutputFlags(); + #ifdef __cplusplus } #endif diff --git a/libwvdrmengine/oemcrypto/include/level3.h b/libwvdrmengine/oemcrypto/include/level3.h index b49f6c0b..6fd157bc 100644 --- a/libwvdrmengine/oemcrypto/include/level3.h +++ b/libwvdrmengine/oemcrypto/include/level3.h @@ -142,6 +142,8 @@ namespace wvoec3 { #define Level3_CreateOldUsageEntry _oecc70 #endif +#define Level3_GetInitializationState _oecl3o01 + extern "C" { bool Level3_IsInApp(); @@ -348,6 +350,30 @@ OEMCryptoResult Level3_CreateOldUsageEntry(uint64_t time_since_license_received, const uint8_t* pst, size_t pst_length); +/* + * Level3_GetInitializationState + * + * Description: + * Return any warning or error condition which occurred during + * initialization. On some platforms, this value will be logged and metrics + * will be gathered on production devices. This is an optional feature, and + * OEMCrypto may always return 0, even if Level3_Initialize failed. This + * function may be called whether Level3_Initialize succeeded or not. + * + * Parameters: + * N/A + * + * Threading: + * No other function calls will be made while this function is running. + * + * Returns: + * 0 - no warnings or errors during initialization + * + * Version: + * This method is new in API version 14. + */ +OEMCryptoResult Level3_GetInitializationState(void); + } // extern "C" // The following are interfaces needed for Level3 OEMCrypto specifically, which