// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #include #include "haystack.h" #include "level3.h" bool Level3_IsInApp() { return haystack::Haystack_IsInApp(); } OEMCryptoResult Level3_Initialize() { return haystack::Haystack_Initialize(); } OEMCryptoResult Level3_Terminate() { return haystack::Haystack_Terminate(); } OEMCryptoResult Level3_OpenSession(OEMCrypto_SESSION* session) { return haystack::Haystack_OpenSession(session); } OEMCryptoResult Level3_CloseSession(OEMCrypto_SESSION session) { return haystack::Haystack_CloseSession(session); } OEMCryptoResult Level3_GenerateDerivedKeys(OEMCrypto_SESSION session, const uint8_t* mac_key_context, size_t mac_key_context_length, const uint8_t* enc_key_context, size_t enc_key_context_length) { return haystack::Haystack_GenerateDerivedKeys( session, mac_key_context, mac_key_context_length, enc_key_context, enc_key_context_length); } OEMCryptoResult Level3_GenerateNonce(OEMCrypto_SESSION session, uint32_t* nonce) { return haystack::Haystack_GenerateNonce(session, nonce); } OEMCryptoResult Level3_PrepAndSignProvisioningRequest( OEMCrypto_SESSION session, uint8_t* message, size_t message_length, size_t* core_message_length, uint8_t* signature, size_t* signature_length) { return haystack::Haystack_PrepAndSignProvisioningRequest( session, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_PrepAndSignLicenseRequest( OEMCrypto_SESSION session, uint8_t* message, size_t message_length, size_t* core_message_length, uint8_t* signature, size_t* signature_length) { return haystack::Haystack_PrepAndSignLicenseRequest( session, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_PrepAndSignRenewalRequest( OEMCrypto_SESSION session, uint8_t* message, size_t message_length, size_t* core_message_length, uint8_t* signature, size_t* signature_length) { return haystack::Haystack_PrepAndSignRenewalRequest( session, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_QueryKeyControl(OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length, uint8_t* key_control_block, size_t* key_control_block_length) { return haystack::Haystack_QueryKeyControl(session, key_id, key_id_length, key_control_block, key_control_block_length); } OEMCryptoResult Level3_GetEmbeddedDrmCertificate( uint8_t* public_cert, size_t* public_cert_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_DecryptCENC_V17( OEMCrypto_SESSION session, const OEMCrypto_SampleDescription* samples, size_t samples_length, const OEMCrypto_CENCEncryptPatternDesc* pattern) { return haystack::Haystack_DecryptCENC_V17(session, samples, samples_length, pattern); } OEMCryptoResult Level3_IsKeyboxOrOEMCertValid() { return haystack::Haystack_IsKeyboxOrOEMCertValid(); } OEMCryptoResult Level3_GetOEMPublicCertificate(uint8_t* public_cert, size_t* public_cert_length) { return haystack::Haystack_GetOEMPublicCertificate(public_cert, public_cert_length); } OEMCryptoResult Level3_GetDeviceID(uint8_t* deviceID, size_t* idLength) { return haystack::Haystack_GetDeviceID(deviceID, idLength); } OEMCryptoResult Level3_LoadOEMPrivateKey(OEMCrypto_SESSION session) { return haystack::Haystack_LoadOEMPrivateKey(session); } OEMCryptoResult Level3_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) { return haystack::Haystack_LoadProvisioning_V18( session, message, message_length, core_message_length, signature, signature_length, wrapped_private_key, wrapped_private_key_length); } OEMCryptoResult Level3_LoadDRMPrivateKey(OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type, const uint8_t* wrapped_rsa_key, size_t wrapped_rsa_key_length) { return haystack::Haystack_LoadDRMPrivateKey( session, key_type, wrapped_rsa_key, wrapped_rsa_key_length); } OEMCryptoResult Level3_DeriveKeysFromSessionKey(OEMCrypto_SESSION session, const uint8_t* enc_session_key, size_t enc_session_key_length, const uint8_t* mac_key_context, size_t mac_key_context_length, const uint8_t* enc_key_context, size_t enc_key_context_length) { return haystack::Haystack_DeriveKeysFromSessionKey( session, enc_session_key, enc_session_key_length, mac_key_context, mac_key_context_length, enc_key_context, enc_key_context_length); } OEMCryptoResult Level3_GetNumberOfOpenSessions(size_t* count) { return haystack::Haystack_GetNumberOfOpenSessions(count); } OEMCryptoResult Level3_GetMaxNumberOfSessions(size_t* maximum) { return haystack::Haystack_GetMaxNumberOfSessions(maximum); } OEMCryptoResult Level3_Generic_Encrypt_V17( OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) { return haystack::Haystack_Generic_Encrypt_V17( session, in_buffer, buffer_length, iv, algorithm, out_buffer); } OEMCryptoResult Level3_Generic_Decrypt_V17( OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) { return haystack::Haystack_Generic_Decrypt_V17( session, in_buffer, buffer_length, iv, algorithm, out_buffer); } OEMCryptoResult Level3_Generic_Sign_V17(OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, OEMCrypto_Algorithm algorithm, uint8_t* signature, size_t* signature_length) { return haystack::Haystack_Generic_Sign_V17(session, in_buffer, buffer_length, algorithm, signature, signature_length); } OEMCryptoResult Level3_Generic_Verify_V17(OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, OEMCrypto_Algorithm algorithm, const uint8_t* signature, size_t signature_length) { return haystack::Haystack_Generic_Verify_V17(session, in_buffer, buffer_length, algorithm, signature, signature_length); } OEMCryptoResult Level3_DeactivateUsageEntry(OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) { return haystack::Haystack_DeactivateUsageEntry(session, pst, pst_length); } OEMCryptoResult Level3_ReportUsage(OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length, uint8_t* buffer, size_t* buffer_length) { return haystack::Haystack_ReportUsage(session, pst, pst_length, buffer, buffer_length); } OEMCryptoResult Level3_CreateUsageTableHeader(uint8_t* header_buffer, size_t* header_buffer_length) { return haystack::Haystack_CreateUsageTableHeader(header_buffer, header_buffer_length); } OEMCryptoResult Level3_LoadUsageTableHeader(const uint8_t* buffer, size_t buffer_length) { return haystack::Haystack_LoadUsageTableHeader(buffer, buffer_length); } OEMCryptoResult Level3_CreateNewUsageEntry(OEMCrypto_SESSION session, uint32_t* usage_entry_number) { return haystack::Haystack_CreateNewUsageEntry(session, usage_entry_number); } OEMCryptoResult Level3_ReuseUsageEntry(OEMCrypto_SESSION session, uint32_t usage_entry_number) { return haystack::Haystack_ReuseUsageEntry(session, usage_entry_number); } OEMCryptoResult Level3_LoadUsageEntry(OEMCrypto_SESSION session, uint32_t index, const uint8_t* buffer, size_t buffer_size) { return haystack::Haystack_LoadUsageEntry(session, index, buffer, buffer_size); } OEMCryptoResult Level3_UpdateUsageEntry(OEMCrypto_SESSION session, uint8_t* header_buffer, size_t* header_buffer_length, uint8_t* entry_buffer, size_t* entry_buffer_length) { return haystack::Haystack_UpdateUsageEntry(session, header_buffer, header_buffer_length, entry_buffer, entry_buffer_length); } OEMCryptoResult Level3_ShrinkUsageTableHeader(uint32_t new_table_size, uint8_t* header_buffer, size_t* header_buffer_length) { return haystack::Haystack_ShrinkUsageTableHeader( new_table_size, header_buffer, header_buffer_length); } OEMCryptoResult Level3_MoveEntry(OEMCrypto_SESSION session, uint32_t new_index) { return haystack::Haystack_MoveEntry(session, new_index); } OEMCryptoResult Level3_SelectKey(const OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length, OEMCryptoCipherMode cipher_mode) { return haystack::Haystack_SelectKey(session, key_id, key_id_length, cipher_mode); } OEMCryptoResult Level3_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) { return haystack::Haystack_LoadLicense_V18(session, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_SetDecryptHash(OEMCrypto_SESSION session, uint32_t frame_number, uint32_t crc32) { return haystack::Haystack_SetDecryptHash(session, frame_number, crc32); } OEMCryptoResult Level3_GetHashErrorCode(OEMCrypto_SESSION session, uint32_t* failed_frame_number) { return haystack::Haystack_GetHashErrorCode(session, failed_frame_number); } OEMCryptoResult Level3_BuildInformation(char* buffer, size_t* buffer_length) { return haystack::Haystack_BuildInformation(buffer, buffer_length); } OEMCryptoResult Level3_LoadRenewal(OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, size_t core_message_length, const uint8_t* signature, size_t signature_length) { return haystack::Haystack_LoadRenewal(session, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_LoadEntitledContentKeys( OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) { return haystack::Haystack_LoadEntitledContentKeys( session, message, message_length, num_keys, key_array); } Level3InitializationState Level3_GetInitializationState() { return haystack::Haystack_GetInitializationState(); } void Level3_OutputErrorLogs() { haystack::Haystack_OutputErrorLogs(); } OEMCryptoResult Level3_CreateEntitledKeySession( OEMCrypto_SESSION oec_session, OEMCrypto_SESSION* key_session) { return haystack::Haystack_CreateEntitledKeySession(oec_session, key_session); } OEMCryptoResult Level3_RemoveEntitledKeySession(OEMCrypto_SESSION key_session) { return haystack::Haystack_RemoveEntitledKeySession(key_session); } OEMCryptoResult Level3_ReassociateEntitledKeySession( OEMCrypto_SESSION key_session, OEMCrypto_SESSION oec_session) { return haystack::Haystack_ReassociateEntitledKeySession(key_session, oec_session); } OEMCryptoResult Level3_GetKeyHandle(OEMCrypto_SESSION session, const uint8_t* content_key_id, size_t content_key_id_length, OEMCryptoCipherMode cipher_mode, uint8_t* key_handle, size_t* key_handle_length) { return haystack::Haystack_GetKeyHandle(session, content_key_id, content_key_id_length, cipher_mode, key_handle, key_handle_length); } OEMCryptoResult Level3_DecryptCENC( const uint8_t* key_handle, size_t key_handle_length, const OEMCrypto_SampleDescription* samples, size_t samples_length, const OEMCrypto_CENCEncryptPatternDesc* pattern) { return haystack::Haystack_DecryptCENC(key_handle, key_handle_length, samples, samples_length, pattern); } OEMCryptoResult Level3_Generic_Encrypt(const uint8_t* key_handle, size_t key_handle_length, const OEMCrypto_SharedMemory* in_buffer, size_t in_buffer_length, const uint8_t* iv, OEMCrypto_Algorithm algorithm, OEMCrypto_SharedMemory* out_buffer) { return haystack::Haystack_Generic_Encrypt(key_handle, key_handle_length, in_buffer, in_buffer_length, iv, algorithm, out_buffer); } OEMCryptoResult Level3_Generic_Decrypt(const uint8_t* key_handle, size_t key_handle_length, const OEMCrypto_SharedMemory* in_buffer, size_t in_buffer_length, const uint8_t* iv, OEMCrypto_Algorithm algorithm, OEMCrypto_SharedMemory* out_buffer) { return haystack::Haystack_Generic_Decrypt(key_handle, key_handle_length, in_buffer, in_buffer_length, iv, algorithm, out_buffer); } OEMCryptoResult Level3_Generic_Sign(const uint8_t* key_handle, size_t key_handle_length, const OEMCrypto_SharedMemory* buffer, size_t buffer_length, OEMCrypto_Algorithm algorithm, OEMCrypto_SharedMemory* signature, size_t* signature_length) { return haystack::Haystack_Generic_Sign(key_handle, key_handle_length, buffer, buffer_length, algorithm, signature, signature_length); } OEMCryptoResult Level3_Generic_Verify(const uint8_t* key_handle, size_t key_handle_length, const OEMCrypto_SharedMemory* buffer, size_t buffer_length, OEMCrypto_Algorithm algorithm, const OEMCrypto_SharedMemory* signature, size_t signature_length) { return haystack::Haystack_Generic_Verify(key_handle, key_handle_length, buffer, buffer_length, algorithm, signature, signature_length); } OEMCryptoResult Level3_InstallKeyboxOrOEMCert(const uint8_t* rot, size_t rotLength) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_WrapKeyboxOrOEMCert(const uint8_t* rot, size_t rotLength, uint8_t* wrappedRot, size_t* wrappedRotLength, const uint8_t* transportKey, size_t transportKeyLength) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCrypto_ProvisioningMethod Level3_GetProvisioningMethod() { return OEMCrypto_OEMCertificate; } OEMCryptoResult Level3_GetKeyData(uint8_t* keyData, size_t* keyDataLength) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_LoadTestRSAKey() { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) { /* This API is for cast receivers only, and can be ignored by L3 * implementation */ return OEMCrypto_ERROR_NOT_IMPLEMENTED; } uint32_t Level3_APIVersion() { return 18; } uint32_t Level3_MinorAPIVersion() { return 3; } uint8_t Level3_SecurityPatchLevel() { return 0; } OEMCrypto_Security_Level Level3_SecurityLevel() { return OEMCrypto_Level3; } OEMCryptoResult Level3_GetHDCPCapability(OEMCrypto_HDCP_Capability* current, OEMCrypto_HDCP_Capability* maximum) { if (current == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; if (maximum == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; *current = HDCP_NONE; *maximum = HDCP_NONE; return OEMCrypto_SUCCESS; } bool Level3_SupportsUsageTable() { return true; } bool Level3_IsAntiRollbackHwPresent() { return false; } uint32_t Level3_SupportedCertificates() { return OEMCrypto_Supports_RSA_2048bit; } OEMCryptoResult Level3_GetCurrentSRMVersion(uint16_t* version) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } uint32_t Level3_GetAnalogOutputFlags() { return OEMCrypto_No_Analog_Output; } OEMCryptoResult Level3_LoadTestKeybox(const uint8_t* buffer, size_t length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_SetSandbox(const uint8_t* sandbox_id, size_t sandbox_id_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } uint32_t Level3_ResourceRatingTier() { return 1; } uint32_t Level3_SupportsDecryptHash() { return OEMCrypto_CRC_Clear_Buffer; } OEMCryptoResult Level3_CopyBuffer( OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length, const OEMCrypto_DestBufferDesc* out_buffer_descriptor, uint8_t subsample_flags) { if (data_addr == nullptr) return OEMCrypto_ERROR_INVALID_CONTEXT; if (out_buffer_descriptor == nullptr) return OEMCrypto_ERROR_INVALID_CONTEXT; if (out_buffer_descriptor->type != OEMCrypto_BufferType_Clear) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } if (out_buffer_descriptor->buffer.clear.clear_buffer_length < data_length) { return OEMCrypto_ERROR_SHORT_BUFFER; } if (out_buffer_descriptor->buffer.clear.clear_buffer == nullptr) { return OEMCrypto_ERROR_INVALID_CONTEXT; } std::memmove(out_buffer_descriptor->buffer.clear.clear_buffer, data_addr, data_length); return OEMCrypto_SUCCESS; } size_t Level3_MaximumUsageTableHeaderSize() { return 0; /* No size limit */ } OEMCryptoResult Level3_AllocateSecureBuffer( OEMCrypto_SESSION session, size_t buffer_size, OEMCrypto_DestBufferDesc* output_descriptor, int* secure_fd) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_FreeSecureBuffer( OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor, int secure_fd) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_GetBootCertificateChain( uint8_t* bcc, size_t* bcc_size, uint8_t* additional_signature, size_t* additional_signature_size) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_GenerateCertificateKeyPair( OEMCrypto_SESSION session, uint8_t* public_key, size_t* public_key_size, uint8_t* public_key_signature, size_t* public_key_signature_size, uint8_t* wrapped_private_key, size_t* wrapped_private_key_size, OEMCrypto_PrivateKeyType* key_type) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_InstallOemPrivateKey(OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type, const uint8_t* wrapped_private_key, size_t wrapped_private_key_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_LoadCasECMKeys( OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, const OEMCrypto_EntitledContentKeyObject* even_key, const OEMCrypto_EntitledContentKeyObject* odd_key) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_ProductionReady() { #if defined(NO_ENCRYPT_NEEDLES) || defined(DEBUG_OBFUS) return OEMCrypto_ERROR_UNKNOWN_FAILURE; #else return OEMCrypto_SUCCESS; #endif } OEMCryptoResult Level3_Idle(OEMCrypto_IdleState state, uint32_t os_specific_code) { return OEMCrypto_SUCCESS; } OEMCryptoResult Level3_Wake() { return OEMCrypto_SUCCESS; } OEMCryptoResult Level3_GetDTCP2Capability( OEMCrypto_DTCP2_Capability* capability) { if (capability == nullptr) return OEMCrypto_ERROR_INVALID_CONTEXT; *capability = OEMCrypto_NO_DTCP2; return OEMCrypto_SUCCESS; } OEMCrypto_WatermarkingSupport Level3_GetWatermarkingSupport() { return OEMCrypto_WatermarkingNotSupported; } OEMCryptoResult Level3_GetOEMKeyToken(OEMCrypto_SESSION key_session, uint8_t* key_token, size_t* key_token_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_GetDeviceInformation(uint8_t* device_info, size_t* device_info_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_GetDeviceSignedCsrPayload( const uint8_t* challenge, size_t challenge_length, const uint8_t* encoded_device_info, size_t encoded_device_info_length, uint8_t* signed_csr_payload, size_t* signed_csr_payload_length) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_SetMaxAPIVersion(uint32_t max_version) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_GetSignatureHashAlgorithm( OEMCrypto_SESSION session, OEMCrypto_SignatureHashAlgorithm* algorithm) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_EnterTestMode(void) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_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) { return haystack::Haystack_LoadLicense( session, context, context_length, derivation_key, derivation_key_length, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_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) { return haystack::Haystack_LoadProvisioning( session, provision_request, provision_request_length, message, message_length, core_message_length, signature, signature_length, wrapped_private_key, wrapped_private_key_length); } OEMCryptoResult Level3_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) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } OEMCryptoResult Level3_PrepAndSignReleaseRequest( OEMCrypto_SESSION session, uint8_t* message, size_t message_length, size_t* core_message_size, uint8_t* signature, size_t* signature_length) { return haystack::Haystack_PrepAndSignReleaseRequest( session, message, message_length, core_message_size, signature, signature_length); } OEMCryptoResult Level3_LoadRelease(OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, size_t core_message_length, const uint8_t* signature, size_t signature_length) { return haystack::Haystack_LoadRelease(session, message, message_length, core_message_length, signature, signature_length); } OEMCryptoResult Level3_GetBCCType(OEMCrypto_BCCType* bcc_type) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; }