From fa055673d500c195ea4d4146fb6a409308b9d7a8 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Wed, 11 Mar 2015 11:04:34 -0700 Subject: [PATCH 1/2] Add test for OEMCrypto_ERROR_TOO_MANY_SESSIONS Also restore the requirement that OEMCrypto shall support at least 8 sessions. Bug: 19641109 Merged from Widevine CDM repo: https://widevine-internal-review.googlesource.com/#/c/13570/ Change-Id: I0aca81b9fe1f4f6505ddf91bcf399ac910b654aa --- .../mock/src/oemcrypto_engine_mock.h | 6 +++++ .../oemcrypto/mock/src/oemcrypto_mock.cpp | 8 ++++-- .../oemcrypto/test/oemcrypto_test.cpp | 27 ++++++++++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) 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 39e4eba0..3dc97cce 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) { From c88c6810502539f6c6b1a9389ea1923032852565 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Thu, 12 Mar 2015 15:12:14 -0700 Subject: [PATCH 2/2] Make GetMaxNumberOfSessions and GetNumberOfOpenSessions security level aware Merged from Widevine CDM repo: https://widevine-internal-review.googlesource.com/#/c/13662/ Change-Id: Id261ab16c4f987dbee78b3ecde4beebbf44f5371 --- .../cdm/core/include/oemcrypto_adapter.h | 4 ++ .../cdm/core/src/crypto_session.cpp | 6 ++- .../core/src/oemcrypto_adapter_dynamic.cpp | 38 +++++++++++-------- 3 files changed, 30 insertions(+), 18 deletions(-) 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 aba6500f..9fb8c4aa 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -994,7 +994,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; @@ -1012,7 +1013,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(