diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 1473c000..22f3c2e9 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -141,17 +141,19 @@ class CryptoSession { const std::string& signature); // Usage table header and usage entry related methods + virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type); virtual CdmResponseType CreateUsageTableHeader( - std::string* usage_table_header); + CdmUsageTableHeader* usage_table_header); virtual CdmResponseType LoadUsageTableHeader( - const std::string& usage_table_header); + const CdmUsageTableHeader& 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); + const CdmUsageEntry& usage_entry); + virtual CdmResponseType UpdateUsageEntry( + CdmUsageTableHeader* usage_table_header, + CdmUsageEntry* usage_entry); + virtual CdmResponseType ShrinkUsageTableHeader( + uint32_t new_entry_count, CdmUsageTableHeader* usage_table_header); virtual CdmResponseType MoveUsageEntry(uint32_t new_entry_number); virtual CdmResponseType CopyOldUsageEntry( const std::string& provider_session_token); @@ -212,6 +214,9 @@ class CryptoSession { KeyId cached_key_id_; + bool is_usage_support_type_valid_; + CdmUsageSupportType usage_support_type_; + uint64_t request_id_base_; static uint64_t request_id_index_; diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index 2ce212d8..8a669a13 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -69,7 +69,7 @@ class DeviceFiles { int64_t last_playback_time, int64_t grace_period_end_time, const CdmAppParameterMap& app_parameters, - const std::string& usage_entry); + const CdmUsageEntry& usage_entry); virtual bool RetrieveLicense( const std::string& key_set_id, LicenseState* state, CdmInitData* pssh_data, CdmKeyMessage* key_request, @@ -77,7 +77,7 @@ class DeviceFiles { CdmKeyResponse* key_renewal_response, std::string* release_server_url, int64_t* playback_start_time, int64_t* last_playback_time, int64_t* grace_period_end_time, CdmAppParameterMap* app_parameters, - std::string* usage_entry); + CdmUsageEntry* usage_entry); virtual bool DeleteLicense(const std::string& key_set_id); virtual bool ListLicenses(std::vector* key_set_ids); virtual bool DeleteAllFiles(); @@ -91,7 +91,7 @@ class DeviceFiles { const CdmKeyResponse& key_response, const std::string& app_id, const std::string& key_set_id, - const std::string& usage_entry); + const CdmUsageEntry& usage_entry); virtual bool DeleteUsageInfo(const std::string& app_id, const std::string& provider_session_token); // Delete usage information from the file system. Puts a list of all the @@ -110,14 +110,14 @@ class DeviceFiles { const std::string& provider_session_token, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - std::string* usage_entry); + CdmUsageEntry* usage_entry); // Retrieve the usage info entry specified by |key_set_id|. // Returns false if the entry could not be found. virtual bool RetrieveUsageInfoByKeySetId(const std::string& app_id, const std::string& key_set_id, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - std::string* usage_entry); + CdmUsageEntry* usage_entry); virtual bool StoreHlsAttributes(const std::string& key_set_id, const CdmHlsMethod method, @@ -128,11 +128,11 @@ class DeviceFiles { virtual bool DeleteHlsAttributes(const std::string& key_set_id); virtual bool StoreUsageTableInfo( - const std::string& usage_table_header, + const CdmUsageTableHeader& usage_table_header, const std::vector& usage_entry_info); virtual bool RetrieveUsageTableInfo( - std::string* usage_table_header, + CdmUsageTableHeader* usage_table_header, std::vector* usage_entry_info); private: diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 115d24c8..045b3fa6 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -28,6 +28,8 @@ typedef std::vector CdmUsageInfo; typedef std::string CdmUsageInfoReleaseMessage; typedef std::string CdmProvisioningRequest; typedef std::string CdmProvisioningResponse; +typedef std::string CdmUsageTableHeader; +typedef std::string CdmUsageEntry; enum CdmKeyRequestType { kKeyRequestTypeUnknown, @@ -274,6 +276,9 @@ enum CdmResponseType { INVALID_PARAMETERS_ENG_22, STORE_LICENSE_ERROR_4, /* 235 */ LIST_LICENSES_ERROR, + INVALID_PARAMETERS_ENG_23, + USAGE_INFORMATION_SUPPORT_FAILED, + USAGE_SUPPORT_GET_API_FAILED, }; enum CdmKeyStatus { @@ -346,6 +351,19 @@ enum CdmClientTokenType { kClientTokenOemCert }; +// kNonSecureUsageSupport - TEE does not provide any support for usage +// information. +// kUsageTableSupport - TEE persists usage information securely in a fixed +// size table, commonly 50 entries. (OEMCrypto v9+) +// kUsageEntrySupport - usage information (table headers and entries) are +// persisted in non-secure storage but are loaded and unloaded from +// the TEE during use (OEMCrypto v13+) +enum CdmUsageSupportType { + kNonSecureUsageSupport, + kUsageTableSupport, + kUsageEntrySupport, +}; + class CdmKeyAllowedUsage { public: CdmKeyAllowedUsage() { diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 2ea19f4b..0b630b8c 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -31,6 +31,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; +const size_t kOemCryptoApiVersionSupportsBigUsageTables = 13; } namespace wvcdm { @@ -46,6 +47,8 @@ CryptoSession::CryptoSession(metrics::MetricsGroup* metrics) update_usage_table_after_close_session_(false), is_destination_buffer_type_valid_(false), requested_security_level_(kLevelDefault), + is_usage_support_type_valid_(false), + usage_support_type_(kNonSecureUsageSupport), request_id_base_(0), cipher_mode_(kCipherModeCtr) { Init(); @@ -120,24 +123,23 @@ void CryptoSession::Terminate() { } bool CryptoSession::GetTokenFromKeybox(std::string* token) { - OEMCryptoResult status; std::string temp_buffer(KEYBOX_KEY_DATA_SIZE, '\0'); // lock is held by caller size_t buf_size = temp_buffer.size(); uint8_t* buf = reinterpret_cast(&temp_buffer[0]); - OEMCryptoResult sts; + OEMCryptoResult status; M_TIME( - sts = OEMCrypto_GetKeyData( + status = OEMCrypto_GetKeyData( buf, &buf_size, requested_security_level_), metrics_, oemcrypto_get_key_data_, - sts, + status, metrics::Pow2Bucket(buf_size), requested_security_level_); - if (OEMCrypto_SUCCESS == sts) { + if (OEMCrypto_SUCCESS == status) { token->swap(temp_buffer); return true; } @@ -1811,8 +1813,47 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message, return NO_ERROR; } +CdmResponseType CryptoSession::GetUsageSupportType( + CdmUsageSupportType* usage_support_type) { + LOGV("GetUsageSupportType: id=%ld", (uint32_t)oec_session_id_); + + if (usage_support_type == NULL) { + LOGE("GetUsageSupportType: usage_support_type param not provided"); + return INVALID_PARAMETERS_ENG_23; + } + + if (is_usage_support_type_valid_) { + *usage_support_type = usage_support_type_; + return NO_ERROR; + } + + bool has_support = false; + if (!UsageInformationSupport(&has_support)) { + LOGE("GetUsageSupportType: UsageInformationSupport failed"); + return USAGE_INFORMATION_SUPPORT_FAILED; + } + + if (!has_support) { + *usage_support_type = usage_support_type_ = kNonSecureUsageSupport; + is_usage_support_type_valid_ = true; + return NO_ERROR; + } + + uint32_t api_version = 0; + if (!GetApiVersion(&api_version)) { + LOGE("GetUsageSupportType: GetApiVersion failed"); + return USAGE_SUPPORT_GET_API_FAILED; + } + + *usage_support_type = usage_support_type_ = + (api_version >= kOemCryptoApiVersionSupportsBigUsageTables) ? + kUsageEntrySupport : kUsageTableSupport; + is_usage_support_type_valid_ = true; + return NO_ERROR; +} + CdmResponseType CryptoSession::CreateUsageTableHeader( - std::string* usage_table_header) { + CdmUsageTableHeader* usage_table_header) { LOGV("CreateUsageTableHeader: id=%ld", (uint32_t)oec_session_id_); if (usage_table_header == NULL) { @@ -1848,7 +1889,7 @@ CdmResponseType CryptoSession::CreateUsageTableHeader( } CdmResponseType CryptoSession::LoadUsageTableHeader( - const std::string& usage_table_header) { + const CdmUsageTableHeader& usage_table_header) { LOGV("LoadUsageTableHeader: id=%ld", (uint32_t)oec_session_id_); OEMCryptoResult result = OEMCrypto_LoadUsageTableHeader( @@ -1908,8 +1949,9 @@ CdmResponseType CryptoSession::CreateUsageEntry(uint32_t* entry_number) { } } -CdmResponseType CryptoSession::LoadUsageEntry(uint32_t entry_number, - const std::string& usage_entry) { +CdmResponseType CryptoSession::LoadUsageEntry( + uint32_t entry_number, + const CdmUsageEntry& usage_entry) { LOGV("LoadUsageEntry: id=%ld", (uint32_t)oec_session_id_); OEMCryptoResult result = OEMCrypto_LoadUsageEntry( @@ -1937,8 +1979,9 @@ CdmResponseType CryptoSession::LoadUsageEntry(uint32_t entry_number, } } -CdmResponseType CryptoSession::UpdateUsageEntry(std::string* usage_table_header, - std::string* usage_entry) { +CdmResponseType CryptoSession::UpdateUsageEntry( + CdmUsageTableHeader* usage_table_header, + CdmUsageEntry* usage_entry) { LOGV("UpdateUsageEntry: id=%ld", (uint32_t)oec_session_id_); if (usage_table_header == NULL) { @@ -1979,27 +2022,26 @@ CdmResponseType CryptoSession::UpdateUsageEntry(std::string* usage_table_header, 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_); +CdmResponseType CryptoSession::ShrinkUsageTableHeader( + uint32_t new_entry_count, CdmUsageTableHeader* usage_table_header) { + LOGV("ShrinkUsageTableHeader: id=%ld", (uint32_t)oec_session_id_); if (usage_table_header == NULL) { LOGE( - "DecrementUsageTableHeaderSize: usage_table_header param not " - "provided"); + "ShrinkUsageTableHeader: 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, + requested_security_level_, new_entry_count, 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, + requested_security_level_, new_entry_count, reinterpret_cast( const_cast(usage_table_header->data())), &usage_table_header_len); @@ -2007,8 +2049,7 @@ CdmResponseType CryptoSession::DecrementUsageTableHeaderSize( if (result != OEMCrypto_SUCCESS) { LOGE( - "DecrementUsageTableHeaderSize: OEMCrypto_ShrinkUsageTableHeader " - "error: %d", + "ShrinkUsageTableHeader: OEMCrypto_ShrinkUsageTableHeader error: %d", result); return SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR; } diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index 30d8c303..eff98e2c 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -177,7 +177,7 @@ bool DeviceFiles::StoreLicense( const std::string& release_server_url, int64_t playback_start_time, int64_t last_playback_time, int64_t grace_period_end_time, const CdmAppParameterMap& app_parameters, - const std::string& usage_entry) { + const CdmUsageEntry& usage_entry) { if (!initialized_) { LOGW("DeviceFiles::StoreLicense: not initialized"); return false; @@ -233,7 +233,7 @@ bool DeviceFiles::RetrieveLicense( CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal, std::string* release_server_url, int64_t* playback_start_time, int64_t* last_playback_time, int64_t* grace_period_end_time, - CdmAppParameterMap* app_parameters, std::string* usage_entry) { + CdmAppParameterMap* app_parameters, CdmUsageEntry* usage_entry) { if (!initialized_) { LOGW("DeviceFiles::RetrieveLicense: not initialized"); return false; @@ -319,7 +319,7 @@ bool DeviceFiles::ListLicenses(std::vector* key_set_ids) { // Scan list of returned filenames, remove extension, and return // as a list of key_set_ids. key_set_ids->clear(); - for (int i = 0; i < filenames.size(); i++) { + for (size_t i = 0; i < filenames.size(); i++) { std::string* name = &filenames[i]; std::size_t pos = name->find(kLicenseFileNameExt); if (pos == std::string::npos) { @@ -384,7 +384,7 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token, const CdmKeyResponse& key_response, const std::string& app_id, const std::string& key_set_id, - const std::string& usage_entry) { + const CdmUsageEntry& usage_entry) { if (!initialized_) { LOGW("DeviceFiles::StoreUsageInfo: not initialized"); return false; @@ -525,7 +525,7 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id, const std::string& provider_session_token, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - std::string* usage_entry) { + CdmUsageEntry* usage_entry) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageInfo: not initialized"); return false; @@ -555,7 +555,7 @@ bool DeviceFiles::RetrieveUsageInfoByKeySetId( const std::string& key_set_id, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - std::string* usage_entry) { + CdmUsageEntry* usage_entry) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageInfoByKeySetId: not initialized"); return false; @@ -678,7 +678,7 @@ bool DeviceFiles::DeleteHlsAttributes(const std::string& key_set_id) { } bool DeviceFiles::StoreUsageTableInfo( - const std::string& usage_table_header, + const CdmUsageTableHeader& usage_table_header, const std::vector& usage_entry_info) { if (!initialized_) { LOGW("DeviceFiles::StoreUsageTableHeader: not initialized"); @@ -723,7 +723,7 @@ bool DeviceFiles::StoreUsageTableInfo( } bool DeviceFiles::RetrieveUsageTableInfo( - std::string* usage_table_header, + CdmUsageTableHeader* usage_table_header, std::vector* usage_entry_info) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageTableInfo: not initialized"); diff --git a/libwvdrmengine/cdm/core/test/test_printers.cpp b/libwvdrmengine/cdm/core/test/test_printers.cpp index a77930eb..aea9bf6d 100644 --- a/libwvdrmengine/cdm/core/test/test_printers.cpp +++ b/libwvdrmengine/cdm/core/test/test_printers.cpp @@ -519,6 +519,15 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) { break; case LIST_LICENSES_ERROR: *os << "LIST_LICENSES_ERROR"; break; + case INVALID_PARAMETERS_ENG_23: + *os << "INVALID_PARAMETERS_ENG_23"; + break; + case USAGE_INFORMATION_SUPPORT_FAILED: + *os << "USAGE_INFORMATION_SUPPORT_FAILED"; + break; + case USAGE_SUPPORT_GET_API_FAILED: + *os << "USAGE_SUPPORT_GET_API_FAILED"; + break; default: *os << "Unknown CdmResponseType"; diff --git a/libwvdrmengine/include/WVErrors.h b/libwvdrmengine/include/WVErrors.h index bbe74d80..552979cd 100644 --- a/libwvdrmengine/include/WVErrors.h +++ b/libwvdrmengine/include/WVErrors.h @@ -241,10 +241,13 @@ enum { kInvalidParametersEng22 = ERROR_DRM_VENDOR_MIN + 227, kStoreLicenseError4 = ERROR_DRM_VENDOR_MIN + 228, kListLicensesError = ERROR_DRM_VENDOR_MIN + 229, + kInvalidParametersEng23 = ERROR_DRM_VENDOR_MIN + 230, + kUsageInformationSupportFailed = ERROR_DRM_VENDOR_MIN + 231, + kUsageSupportGetApiFailed = ERROR_DRM_VENDOR_MIN + 232, // 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 + 229, + kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 232, // 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 344645c5..d9ff873c 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -473,6 +473,12 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { return kStoreLicenseError4; case wvcdm::LIST_LICENSES_ERROR: return kListLicensesError; + case wvcdm::INVALID_PARAMETERS_ENG_23: + return kInvalidParametersEng23; + case wvcdm::USAGE_INFORMATION_SUPPORT_FAILED: + return kUsageInformationSupportFailed; + case wvcdm::USAGE_SUPPORT_GET_API_FAILED: + return kUsageSupportGetApiFailed; case wvcdm::UNUSED_1: case wvcdm::UNUSED_2: