diff --git a/libwvdrmengine/cdm/Android.mk b/libwvdrmengine/cdm/Android.mk index 700c8b84..2e0e6ade 100644 --- a/libwvdrmengine/cdm/Android.mk +++ b/libwvdrmengine/cdm/Android.mk @@ -18,7 +18,6 @@ LOCAL_STATIC_LIBRARIES := libcdm_protos libcrypto_static SRC_DIR := src CORE_SRC_DIR := core/src -PROFILER_SRC_DIR := profiler/src LOCAL_SRC_FILES := \ $(CORE_SRC_DIR)/buffer_reader.cpp \ @@ -36,6 +35,7 @@ LOCAL_SRC_FILES := \ $(CORE_SRC_DIR)/service_certificate.cpp \ $(SRC_DIR)/wv_content_decryption_module.cpp \ + LOCAL_MODULE := libcdm LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TARGET_ARCH := arm x86 mips diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index dd6dd139..b1a2f3f9 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -138,6 +138,22 @@ class CryptoSession { CdmSigningAlgorithm algorithm, const std::string& signature); + // Usage table header and usage entry related methods + virtual CdmResponseType CreateUsageTableHeader( + std::string* usage_table_header); + virtual CdmResponseType LoadUsageTableHeader( + const std::string& usage_table_header); + virtual CdmResponseType CreateUsageEntry(uint32_t* entry_number); + virtual CdmResponseType LoadUsageEntry(uint32_t entry_number, + const std::string& usage_entry); + virtual CdmResponseType UpdateUsageEntry(std::string* usage_table_header, + std::string* usage_entry); + virtual CdmResponseType DecrementUsageTableHeaderSize( + uint32_t current_usage_table_size, std::string* usage_table_header); + virtual CdmResponseType MoveUsageEntry(uint32_t new_entry_number); + virtual CdmResponseType CopyOldUsageEntry( + const std::string& provider_session_token); + private: bool GetProvisioningMethod(CdmClientTokenType* token_type); void Init(); diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 4908f269..31d29e75 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -252,6 +252,25 @@ enum CdmResponseType { ANALOG_OUTPUT_ERROR, UNKNOWN_SELECT_KEY_ERROR_1, UNKNOWN_SELECT_KEY_ERROR_2, + CREATE_USAGE_TABLE_ERROR, /* 215 */ + LOAD_USAGE_HEADER_GENERATION_SKEW, + LOAD_USAGE_HEADER_SIGNATURE_FAILURE, + LOAD_USAGE_HEADER_BAD_MAGIC, + LOAD_USAGE_HEADER_UNKNOWN_ERROR, + INVALID_PARAMETERS_ENG_17, /* 220 */ + INVALID_PARAMETERS_ENG_18, + INSUFFICIENT_CRYPTO_RESOURCES_3, + CREATE_USAGE_ENTRY_UNKNOWN_ERROR, + LOAD_USAGE_ENTRY_GENERATION_SKEW, + LOAD_USAGE_ENTRY_SIGNATURE_FAILURE, /* 225 */ + LOAD_USAGE_ENTRY_UNKNOWN_ERROR, + INVALID_PARAMETERS_ENG_19, + INVALID_PARAMETERS_ENG_20, + UPDATE_USAGE_ENTRY_UNKNOWN_ERROR, + INVALID_PARAMETERS_ENG_21, /* 230 */ + SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR, + MOVE_USAGE_ENTRY_UNKNOWN_ERROR, + COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR, }; enum CdmKeyStatus { diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 4cedae3e..9eb35085 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -29,6 +29,7 @@ std::string EncodeUint32(unsigned int u) { } const uint32_t kRsaSignatureLength = 256; const size_t kMaximumChunkSize = 100 * 1024; // 100 KiB +const size_t kEstimatedInitialUsageTableHeader = 40; } namespace wvcdm { @@ -507,6 +508,7 @@ CdmResponseType CryptoSession::LoadKeys( uint8_t* srm_req = NULL; if (!srm_requirement.empty()) srm_req = const_cast(msg) + GetOffset(message, srm_requirement); + LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_); OEMCryptoResult sts = OEMCrypto_LoadKeys( oec_session_id_, msg, message.size(), @@ -1462,6 +1464,243 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message, return NO_ERROR; } +CdmResponseType CryptoSession::CreateUsageTableHeader( + std::string* usage_table_header) { + LOGV("CreateUsageTableHeader: id=%ld", (uint32_t)oec_session_id_); + + if (usage_table_header == NULL) { + LOGE("CreateUsageTableHeader: usage_table_header param not provided"); + return INVALID_PARAMETERS_ENG_17; + } + + usage_table_header->resize(kEstimatedInitialUsageTableHeader); + + uint32_t usage_table_header_size = usage_table_header->size(); + OEMCryptoResult result = OEMCrypto_CreateUsageTableHeader( + requested_security_level_, + reinterpret_cast(const_cast(usage_table_header->data())), + &usage_table_header_size); + + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + usage_table_header->resize(usage_table_header_size); + result = OEMCrypto_CreateUsageTableHeader( + requested_security_level_, + reinterpret_cast( + const_cast(usage_table_header->data())), + &usage_table_header_size); + } + + if (result != OEMCrypto_SUCCESS) { + LOGE("CreateUsageTableHeader; usage table header creation failed: %d", + result); + return CREATE_USAGE_TABLE_ERROR; + } + + usage_table_header->resize(usage_table_header_size); + return NO_ERROR; +} + +CdmResponseType CryptoSession::LoadUsageTableHeader( + const std::string& usage_table_header) { + LOGV("LoadUsageTableHeader: id=%ld", (uint32_t)oec_session_id_); + + OEMCryptoResult result = OEMCrypto_LoadUsageTableHeader( + requested_security_level_, + reinterpret_cast(usage_table_header.data()), + usage_table_header.size()); + + if (result != OEMCrypto_SUCCESS) { + if (result == OEMCrypto_WARNING_GENERATION_SKEW) { + LOGW( + "LoadUsageTableHeader: OEMCrypto_LoadUsageTableHeader warning: " + "generation skew"); + } else { + LOGE("LoadUsageTableHeader: OEMCrypto_LoadUsageTableHeader error: %d", + result); + } + } + + switch (result) { + case OEMCrypto_SUCCESS: + case OEMCrypto_WARNING_GENERATION_SKEW: + return NO_ERROR; + case OEMCrypto_ERROR_GENERATION_SKEW: + return LOAD_USAGE_HEADER_GENERATION_SKEW; + case OEMCrypto_ERROR_SIGNATURE_FAILURE: + return LOAD_USAGE_HEADER_SIGNATURE_FAILURE; + case OEMCrypto_ERROR_BAD_MAGIC: + return LOAD_USAGE_HEADER_BAD_MAGIC; + case OEMCrypto_ERROR_UNKNOWN_FAILURE: + default: + return LOAD_USAGE_HEADER_UNKNOWN_ERROR; + } +} + +CdmResponseType CryptoSession::CreateUsageEntry(uint32_t* entry_number) { + LOGV("CreateUsageEntry: id=%ld", (uint32_t)oec_session_id_); + + if (entry_number == NULL) { + LOGE("CreateUsageEntry: entry_number param not provided"); + return INVALID_PARAMETERS_ENG_18; + } + + OEMCryptoResult result = + OEMCrypto_CreateNewUsageEntry(oec_session_id_, entry_number); + + switch (result) { + case OEMCrypto_SUCCESS: + return NO_ERROR; + case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES: + LOGE( + "CreateUsageEntry: OEMCrypto_CreateNewUsageEntry error: " + "Insufficient resources"); + return INSUFFICIENT_CRYPTO_RESOURCES_3; + default: + LOGE("CreateUsageEntry: OEMCrypto_CreateNewUsageEntry error: %d", result); + return CREATE_USAGE_ENTRY_UNKNOWN_ERROR; + } +} + +CdmResponseType CryptoSession::LoadUsageEntry(uint32_t entry_number, + const std::string& usage_entry) { + LOGV("LoadUsageEntry: id=%ld", (uint32_t)oec_session_id_); + + OEMCryptoResult result = OEMCrypto_LoadUsageEntry( + oec_session_id_, entry_number, + reinterpret_cast(usage_entry.data()), usage_entry.size()); + + if (result != OEMCrypto_SUCCESS) { + if (result == OEMCrypto_WARNING_GENERATION_SKEW) { + LOGW("LoadUsageEntry: OEMCrypto_LoadUsageEntry warning: generation skew"); + } else { + LOGE("LoadUsageTableHeader: OEMCrypto_LoadUsageEntry error: %d", result); + } + } + + switch (result) { + case OEMCrypto_SUCCESS: + case OEMCrypto_WARNING_GENERATION_SKEW: + return NO_ERROR; + case OEMCrypto_ERROR_GENERATION_SKEW: + return LOAD_USAGE_ENTRY_GENERATION_SKEW; + case OEMCrypto_ERROR_SIGNATURE_FAILURE: + return LOAD_USAGE_ENTRY_SIGNATURE_FAILURE; + default: + return LOAD_USAGE_ENTRY_UNKNOWN_ERROR; + } +} + +CdmResponseType CryptoSession::UpdateUsageEntry(std::string* usage_table_header, + std::string* usage_entry) { + LOGV("UpdateUsageEntry: id=%ld", (uint32_t)oec_session_id_); + + if (usage_table_header == NULL) { + LOGE("UpdateUsageEntry: usage_table_header param not provided"); + return INVALID_PARAMETERS_ENG_19; + } + + if (usage_entry == NULL) { + LOGE("UpdateUsageEntry: usage_entry param not provided"); + return INVALID_PARAMETERS_ENG_20; + } + + size_t usage_table_header_len = 0; + size_t usage_entry_len = 0; + OEMCryptoResult result = OEMCrypto_UpdateUsageEntry( + oec_session_id_, NULL, &usage_table_header_len, NULL, &usage_entry_len); + + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + usage_table_header->resize(usage_table_header_len); + usage_entry->resize(usage_entry_len); + + result = OEMCrypto_UpdateUsageEntry( + oec_session_id_, + reinterpret_cast( + const_cast(usage_table_header->data())), + &usage_table_header_len, + reinterpret_cast(const_cast(usage_entry->data())), + &usage_entry_len); + } + + if (result != OEMCrypto_SUCCESS) { + LOGE("UpdateUsageEntry: OEMCrypto_UpdateUsageEntry error: %d", result); + return UPDATE_USAGE_ENTRY_UNKNOWN_ERROR; + } + + usage_table_header->resize(usage_table_header_len); + usage_entry->resize(usage_entry_len); + return NO_ERROR; +} + +CdmResponseType CryptoSession::DecrementUsageTableHeaderSize( + uint32_t current_usage_table_size, std::string* usage_table_header) { + LOGV("DecrementUsageTableHeaderSize: id=%ld", (uint32_t)oec_session_id_); + + if (usage_table_header == NULL) { + LOGE( + "DecrementUsageTableHeaderSize: usage_table_header param not " + "provided"); + return INVALID_PARAMETERS_ENG_21; + } + + size_t usage_table_header_len = 0; + OEMCryptoResult result = OEMCrypto_ShrinkUsageTableHeader( + requested_security_level_, current_usage_table_size, NULL, + &usage_table_header_len); + + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + usage_table_header->resize(usage_table_header_len); + + result = OEMCrypto_ShrinkUsageTableHeader( + requested_security_level_, --current_usage_table_size, + reinterpret_cast( + const_cast(usage_table_header->data())), + &usage_table_header_len); + } + + if (result != OEMCrypto_SUCCESS) { + LOGE( + "DecrementUsageTableHeaderSize: OEMCrypto_ShrinkUsageTableHeader " + "error: %d", + result); + return SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR; + } + + usage_table_header->resize(usage_table_header_len); + return NO_ERROR; +} + +CdmResponseType CryptoSession::MoveUsageEntry(uint32_t new_entry_number) { + LOGV("MoveUsageEntry: id=%ld", (uint32_t)oec_session_id_); + + OEMCryptoResult result = + OEMCrypto_MoveEntry(oec_session_id_, new_entry_number); + + if (result != OEMCrypto_SUCCESS) { + LOGE("MoveUsageEntry: OEMCrypto_MoveEntry error: %d", result); + return MOVE_USAGE_ENTRY_UNKNOWN_ERROR; + } + + return NO_ERROR; +} + +CdmResponseType CryptoSession::CopyOldUsageEntry( + const std::string& provider_session_token) { + LOGV("CopyOldUsageEntry: id=%ld", (uint32_t)oec_session_id_); + + OEMCryptoResult result = OEMCrypto_CopyOldUsageEntry( + oec_session_id_, + reinterpret_cast(provider_session_token.data()), + provider_session_token.size()); + + if (result != OEMCrypto_SUCCESS) { + LOGE("CopyOldUsageEntry: OEMCrypto_CopyOldUsageEntry error: %d", result); + return COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR; + } + + return NO_ERROR; +} + OEMCrypto_Algorithm CryptoSession::GenericSigningAlgorithm( CdmSigningAlgorithm algorithm) { if (kSigningAlgorithmHmacSha256 == algorithm) { diff --git a/libwvdrmengine/cdm/core/test/test_printers.cpp b/libwvdrmengine/cdm/core/test/test_printers.cpp index 0323d111..61d8b3f9 100644 --- a/libwvdrmengine/cdm/core/test/test_printers.cpp +++ b/libwvdrmengine/cdm/core/test/test_printers.cpp @@ -463,6 +463,57 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) { break; case UNKNOWN_SELECT_KEY_ERROR_2: *os << "UNKNOWN_SELECT_KEY_ERROR_2"; break; + case CREATE_USAGE_TABLE_ERROR: *os << "CREATE_USAGE_TABLE_ERROR"; + break; + case LOAD_USAGE_HEADER_GENERATION_SKEW: + *os << "LOAD_USAGE_HEADER_GENERATION_SKEW"; + break; + case LOAD_USAGE_HEADER_SIGNATURE_FAILURE: + *os << "LOAD_USAGE_HEADER_SIGNATURE_FAILURE"; + break; + case LOAD_USAGE_HEADER_BAD_MAGIC: *os << "LOAD_USAGE_HEADER_BAD_MAGIC"; + break; + case LOAD_USAGE_HEADER_UNKNOWN_ERROR: + *os << "LOAD_USAGE_HEADER_UNKNOWN_ERROR"; + break; + case INVALID_PARAMETERS_ENG_17: *os << "INVALID_PARAMETERS_ENG_17"; + break; + case INVALID_PARAMETERS_ENG_18: *os << "INVALID_PARAMETERS_ENG_18"; + break; + case INSUFFICIENT_CRYPTO_RESOURCES_3: + *os << "INSUFFICIENT_CRYPTO_RESOURCES_3"; + break; + case CREATE_USAGE_ENTRY_UNKNOWN_ERROR: + *os << "CREATE_USAGE_ENTRY_UNKNOWN_ERROR"; + break; + case LOAD_USAGE_ENTRY_GENERATION_SKEW: + *os << "LOAD_USAGE_ENTRY_GENERATION_SKEW"; + break; + case LOAD_USAGE_ENTRY_SIGNATURE_FAILURE: + *os << "LOAD_USAGE_ENTRY_SIGNATURE_FAILURE"; + break; + case LOAD_USAGE_ENTRY_UNKNOWN_ERROR: + *os << "LOAD_USAGE_ENTRY_UNKNOWN_ERROR"; + break; + case INVALID_PARAMETERS_ENG_19: *os << "INVALID_PARAMETERS_ENG_19"; + break; + case INVALID_PARAMETERS_ENG_20: *os << "INVALID_PARAMETERS_ENG_20"; + break; + case UPDATE_USAGE_ENTRY_UNKNOWN_ERROR: + *os << "UPDATE_USAGE_ENTRY_UNKNOWN_ERROR"; + break; + case INVALID_PARAMETERS_ENG_21: *os << "INVALID_PARAMETERS_ENG_21"; + break; + case SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR: + *os << "SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR"; + break; + case MOVE_USAGE_ENTRY_UNKNOWN_ERROR: + *os << "MOVE_USAGE_ENTRY_UNKNOWN_ERROR"; + break; + case COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR: + *os << "COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR"; + break; + default: *os << "Unknown CdmResponseType"; break; diff --git a/libwvdrmengine/cdm/test/unit-test.mk b/libwvdrmengine/cdm/test/unit-test.mk index 5db3bc50..a7aef767 100644 --- a/libwvdrmengine/cdm/test/unit-test.mk +++ b/libwvdrmengine/cdm/test/unit-test.mk @@ -21,8 +21,6 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/android/cdm/test \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/core/test \ - vendor/widevine/libwvdrmengine/cdm/profiler/include \ - vendor/widevine/libwvdrmengine/cdm/profiler/test \ vendor/widevine/libwvdrmengine/cdm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ diff --git a/libwvdrmengine/include/WVErrors.h b/libwvdrmengine/include/WVErrors.h index 6c45826a..53e6b16d 100644 --- a/libwvdrmengine/include/WVErrors.h +++ b/libwvdrmengine/include/WVErrors.h @@ -219,9 +219,29 @@ enum { kLicensingClientTokenError1 = ERROR_DRM_VENDOR_MIN + 205, kUnknownSelectKeyError1 = ERROR_DRM_VENDOR_MIN + 206, kUnknownSelectKeyError2 = ERROR_DRM_VENDOR_MIN + 207, + kCreateUsageTableError = ERROR_DRM_VENDOR_MIN + 208, + kLoadUsageHeaderGenerationSkew = ERROR_DRM_VENDOR_MIN + 209, + kLoadUsageHeaderSignatureFailure = ERROR_DRM_VENDOR_MIN + 210, + kLoadUsageHeaderBadMagic = ERROR_DRM_VENDOR_MIN + 211, + kLoadUsageHeaderUnknownError = ERROR_DRM_VENDOR_MIN + 212, + kInvalidParametersEng17 = ERROR_DRM_VENDOR_MIN + 213, + kInvalidParametersEng18 = ERROR_DRM_VENDOR_MIN + 214, + kInsufficientCryptoResources3 = ERROR_DRM_VENDOR_MIN + 215, + kCreateUsageEntryUnknownError = ERROR_DRM_VENDOR_MIN + 216, + kLoadUsageEntryGenerationSkew = ERROR_DRM_VENDOR_MIN + 217, + kLoadUsageEntrySignatureFailure = ERROR_DRM_VENDOR_MIN + 218, + kLoadUsageEntryUnknownError = ERROR_DRM_VENDOR_MIN + 219, + kInvalidParametersEng19 = ERROR_DRM_VENDOR_MIN + 220, + kInvalidParametersEng20 = ERROR_DRM_VENDOR_MIN + 221, + kUpdateUsageEntryUnknownError = ERROR_DRM_VENDOR_MIN + 222, + kInvalidParametersEng21 = ERROR_DRM_VENDOR_MIN + 223, + kShrinkUsageTablerHeaderUnknownError = ERROR_DRM_VENDOR_MIN + 224, + kMoveUsageEntryUnknownError = ERROR_DRM_VENDOR_MIN + 225, + kCopyOldUsageEntryUnknownError = ERROR_DRM_VENDOR_MIN + 226, + // This should always follow the last error code. // The offset value should be updated each time a new error code is added. - kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 207, + kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 226, // Used by crypto test mode kErrorTestMode = ERROR_DRM_VENDOR_MAX, diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h index 8f902679..674f23f6 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -429,6 +429,45 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { return kUnknownSelectKeyError1; case wvcdm::UNKNOWN_SELECT_KEY_ERROR_2: return kUnknownSelectKeyError2; + case wvcdm::CREATE_USAGE_TABLE_ERROR: + return kCreateUsageTableError; + case wvcdm::LOAD_USAGE_HEADER_GENERATION_SKEW: + return kLoadUsageHeaderGenerationSkew; + case wvcdm::LOAD_USAGE_HEADER_SIGNATURE_FAILURE: + return kLoadUsageHeaderSignatureFailure; + case wvcdm::LOAD_USAGE_HEADER_BAD_MAGIC: + return kLoadUsageHeaderBadMagic; + case wvcdm::LOAD_USAGE_HEADER_UNKNOWN_ERROR: + return kLoadUsageHeaderUnknownError; + case wvcdm::INVALID_PARAMETERS_ENG_17: + return kInvalidParametersEng17; + case wvcdm::INVALID_PARAMETERS_ENG_18: + return kInvalidParametersEng18; + case wvcdm::INSUFFICIENT_CRYPTO_RESOURCES_3: + return kInsufficientCryptoResources3; + case wvcdm::CREATE_USAGE_ENTRY_UNKNOWN_ERROR: + return kCreateUsageEntryUnknownError; + case wvcdm::LOAD_USAGE_ENTRY_GENERATION_SKEW: + return kLoadUsageEntryGenerationSkew; + case wvcdm::LOAD_USAGE_ENTRY_SIGNATURE_FAILURE: + return kLoadUsageEntrySignatureFailure; + case wvcdm::LOAD_USAGE_ENTRY_UNKNOWN_ERROR: + return kLoadUsageEntryUnknownError; + case wvcdm::INVALID_PARAMETERS_ENG_19: + return kInvalidParametersEng19; + case wvcdm::INVALID_PARAMETERS_ENG_20: + return kInvalidParametersEng20; + case wvcdm::UPDATE_USAGE_ENTRY_UNKNOWN_ERROR: + return kUpdateUsageEntryUnknownError; + case wvcdm::INVALID_PARAMETERS_ENG_21: + return kInvalidParametersEng21; + case wvcdm::SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR: + return kShrinkUsageTablerHeaderUnknownError; + case wvcdm::MOVE_USAGE_ENTRY_UNKNOWN_ERROR: + return kMoveUsageEntryUnknownError; + case wvcdm::COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR: + return kCopyOldUsageEntryUnknownError; + case wvcdm::UNUSED_1: case wvcdm::UNUSED_2: case wvcdm::UNUSED_3: