diff --git a/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h b/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h index aeff6e25..d92d2986 100644 --- a/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h +++ b/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h @@ -28,6 +28,10 @@ OEMCryptoResult OEMCrypto_GetHDCPCapability(SecurityLevel level, OEMCrypto_HDCP_Capability* maximum); bool OEMCrypto_SupportsUsageTable(SecurityLevel level); bool OEMCrypto_IsAntiRollbackHwPresent(SecurityLevel level); +OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(SecurityLevel level, + size_t* count); +OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(SecurityLevel level, + size_t* maximum); } // namespace wvcdm #endif // WVCDM_CORE_OEMCRYPTO_ADAPTER_H_ diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index b6f3e171..9c1ba11f 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -993,7 +993,8 @@ bool CryptoSession::GetNumberOfOpenSessions(size_t* count) { } size_t sessions_count; - OEMCryptoResult status = OEMCrypto_GetNumberOfOpenSessions(&sessions_count); + OEMCryptoResult status = OEMCrypto_GetNumberOfOpenSessions( + requested_security_level_, &sessions_count); if (OEMCrypto_SUCCESS != status) { LOGW("OEMCrypto_GetNumberOfOpenSessions fails with %d", status); return false; @@ -1011,7 +1012,8 @@ bool CryptoSession::GetMaxNumberOfSessions(size_t* max) { } size_t max_sessions; - OEMCryptoResult status = OEMCrypto_GetMaxNumberOfSessions(&max_sessions); + OEMCryptoResult status = OEMCrypto_GetMaxNumberOfSessions( + requested_security_level_, &max_sessions); if (OEMCrypto_SUCCESS != status) { LOGW("OEMCrypto_GetMaxNumberOfSessions fails with %d", status); return false; diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp index 58dc7ea2..5cb83b06 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp @@ -568,6 +568,24 @@ bool OEMCrypto_IsAntiRollbackHwPresent(SecurityLevel level) { return fcn->IsAntiRollbackHwPresent(); } +OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(SecurityLevel level, + size_t* count) { + if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE; + const FunctionPointers* fcn = kAdapter->get(level); + if (!fcn) return OEMCrypto_ERROR_INVALID_SESSION; + if (fcn->version < 10) return OEMCrypto_ERROR_NOT_IMPLEMENTED; + return fcn->GetNumberOfOpenSessions(count); +} + +OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(SecurityLevel level, + size_t* maximum) { + if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE; + const FunctionPointers* fcn = kAdapter->get(level); + if (!fcn) return OEMCrypto_ERROR_INVALID_SESSION; + if (fcn->version < 10) return OEMCrypto_ERROR_NOT_IMPLEMENTED; + return fcn->GetMaxNumberOfSessions(maximum); +} + } // namespace wvcdm extern "C" OEMCryptoResult OEMCrypto_Initialize(void) { @@ -795,24 +813,12 @@ extern "C" bool OEMCrypto_IsAntiRollbackHwPresent() { return OEMCrypto_IsAntiRollbackHwPresent(kLevelDefault); } -extern "C" OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* maximum) { - if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - const FunctionPointers* fcn = kAdapter->get(kLevelDefault); - if (!fcn) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - if (fcn->version < 10) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return fcn->GetNumberOfOpenSessions(maximum); +extern "C" OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) { + return OEMCrypto_GetNumberOfOpenSessions(kLevelDefault, count); } -extern "C" OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t *maximum) { - if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - const FunctionPointers* fcn = kAdapter->get(kLevelDefault); - if (!fcn) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - if (fcn->version < 10) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return fcn->GetMaxNumberOfSessions(maximum); +extern "C" OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) { + return OEMCrypto_GetMaxNumberOfSessions(kLevelDefault, maximum); } extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt( diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h index c2be6496..e8248cba 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h @@ -239,6 +239,12 @@ class CryptoEngine { size_t GetNumberOfOpenSessions() { return sessions_.size(); } + size_t GetMaxNumberOfSessions() { + // An arbitrary limit for mock implementation. + static const size_t kMaxSupportedOEMCryptoSessions = 64; + return kMaxSupportedOEMCryptoSessions; + } + void set_current_session_(SessionContext* current) { current_session_ = current; } diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp index 0b01dddf..96826303 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp @@ -80,6 +80,11 @@ OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { LOGI("-- OEMCryptoResult OEMCrypto_OpenSession" "(OEMCrypto_SESSION *session)\n"); } + if (crypto_engine->GetNumberOfOpenSessions() >= + crypto_engine->GetMaxNumberOfSessions()) { + LOGE("[OEMCrypto_OpenSession(): failed due to too many sessions]"); + return OEMCrypto_ERROR_TOO_MANY_SESSIONS; + } SessionId sid = crypto_engine->CreateSession(); *session = (OEMCrypto_SESSION)sid; if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { @@ -1040,8 +1045,7 @@ OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) { LOGI("-- OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(%p)\n", maximum); } if (maximum == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - const size_t kMaxSupportedOEMCryptoSessions = 64; - *maximum = kMaxSupportedOEMCryptoSessions; + *maximum = crypto_engine->GetMaxNumberOfSessions(); return OEMCrypto_SUCCESS; } diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 3a6e7128..eecd6036 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -1746,12 +1746,26 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenClose) { ASSERT_EQ(0, sessions_count); size_t max_sessions; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetMaxNumberOfSessions(&max_sessions)); - ASSERT_GT(max_sessions, 0); + // We expect OEMCrypto implementations support at least 8 sessions. + const size_t kMinimumSupportedMaxNumberOfSessions = 8u; + ASSERT_GE(max_sessions, kMinimumSupportedMaxNumberOfSessions); vector sessions; - for (int i = 0; i < max_sessions; i++) { + // Limit the number of sessions for testing. + const size_t kMaxNumberOfSessionsForTesting = 0x100u; + for (int i = 0; i < kMaxNumberOfSessionsForTesting; i++) { OEMCrypto_SESSION session_id; - ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session_id)); + OEMCryptoResult sts = OEMCrypto_OpenSession(&session_id); + // GetMaxNumberOfSessions might be an estimate. We allow OEMCrypto to report + // a max that is less than what is actually supported. Assume the number + // returned is |max|. OpenSessions shall not fail if number of active + // sessions is less than |max|; OpenSessions should fail with + // OEMCrypto_ERROR_TOO_MANY_SESSIONS if too many sessions are open. + if (sts != OEMCrypto_SUCCESS) { + ASSERT_EQ(OEMCrypto_ERROR_TOO_MANY_SESSIONS, sts); + ASSERT_GE(i, max_sessions); + break; + } ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetNumberOfOpenSessions(&sessions_count)); ASSERT_EQ(i + 1, sessions_count); @@ -1763,6 +1777,13 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenClose) { OEMCrypto_GetNumberOfOpenSessions(&sessions_count)); ASSERT_EQ(sessions.size() - i - 1, sessions_count); } + if (sessions.size() == kMaxNumberOfSessionsForTesting) { + printf( + " MaxSessionsOpenClose: reaches " + "kMaxNumberOfSessionsForTesting(%zu). GetMaxNumberOfSessions = %zu. " + "ERROR_TOO_MANY_SESSIONS not tested.", + kMaxNumberOfSessionsForTesting, max_sessions); + } } TEST_F(OEMCryptoClientTest, GenerateNonce) {