diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eb8bc1..e1130b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ [TOC] +## [Version 17.6][v17.6] + +This is a minor release with minor test improvements. + +### Tests + +- Skip usage table tests on devices that don't support usage tables + ## [Version 17.5][v17.5] This release is mostly testing-focused, including new tests that provide @@ -321,3 +329,4 @@ Public release for OEMCrypto API and ODK library version 16.4. [v17.3]: https://widevine-partner.googlesource.com/oemcrypto/+/refs/tags/v17.3 [v17.4]: https://widevine-partner.googlesource.com/oemcrypto/+/refs/tags/v17.4 [v17.5]: https://widevine-partner.googlesource.com/oemcrypto/+/refs/tags/v17.5 +[v17.6]: https://widevine-partner.googlesource.com/oemcrypto/+/refs/tags/v17.6 diff --git a/oemcrypto/include/OEMCryptoCENC.h b/oemcrypto/include/OEMCryptoCENC.h index 067948d..c44f054 100644 --- a/oemcrypto/include/OEMCryptoCENC.h +++ b/oemcrypto/include/OEMCryptoCENC.h @@ -3,7 +3,7 @@ // License Agreement. /** - * @mainpage OEMCrypto API v17.5 + * @mainpage OEMCrypto API v17.6 * * OEMCrypto is the low level library implemented by the OEM to provide key and * content protection, usually in a separate secure memory or process space. The diff --git a/oemcrypto/odk/include/core_message_features.h b/oemcrypto/odk/include/core_message_features.h index 8c97b12..ccb8777 100644 --- a/oemcrypto/odk/include/core_message_features.h +++ b/oemcrypto/odk/include/core_message_features.h @@ -25,9 +25,9 @@ struct CoreMessageFeatures { // This is the published version of the ODK Core Message library. The default // behavior is for the server to restrict messages to at most this version - // number. The default is 17.5. + // number. The default is 17.6. uint32_t maximum_major_version = 17; - uint32_t maximum_minor_version = 5; + uint32_t maximum_minor_version = 6; bool operator==(const CoreMessageFeatures &other) const; bool operator!=(const CoreMessageFeatures &other) const { diff --git a/oemcrypto/odk/include/odk_structs.h b/oemcrypto/odk/include/odk_structs.h index 0a77f1c..8289501 100644 --- a/oemcrypto/odk/include/odk_structs.h +++ b/oemcrypto/odk/include/odk_structs.h @@ -16,10 +16,10 @@ extern "C" { /* The version of this library. */ #define ODK_MAJOR_VERSION 17 -#define ODK_MINOR_VERSION 5 +#define ODK_MINOR_VERSION 6 /* ODK Version string. Date changed automatically on each release. */ -#define ODK_RELEASE_DATE "ODK v17.5 2024-09-04" +#define ODK_RELEASE_DATE "ODK v17.6 2024-11-04" /* The lowest version number for an ODK message. */ #define ODK_FIRST_VERSION 16 diff --git a/oemcrypto/odk/src/core_message_features.cpp b/oemcrypto/odk/src/core_message_features.cpp index 4f14f6b..10f5ad6 100644 --- a/oemcrypto/odk/src/core_message_features.cpp +++ b/oemcrypto/odk/src/core_message_features.cpp @@ -23,7 +23,7 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures( features.maximum_minor_version = 5; // 16.5 break; case 17: - features.maximum_minor_version = 5; // 17.5 + features.maximum_minor_version = 6; // 17.6 break; default: features.maximum_minor_version = 0; diff --git a/oemcrypto/odk/src/odk_timer.c b/oemcrypto/odk/src/odk_timer.c index 6b2cac8..0f25c67 100644 --- a/oemcrypto/odk/src/odk_timer.c +++ b/oemcrypto/odk/src/odk_timer.c @@ -274,7 +274,7 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits, nonce_values->api_minor_version = 5; break; case 17: - nonce_values->api_minor_version = 5; + nonce_values->api_minor_version = 6; break; case 18: nonce_values->api_minor_version = 3; diff --git a/oemcrypto/odk/test/odk_test.cpp b/oemcrypto/odk/test/odk_test.cpp index e104903..f0ab397 100644 --- a/oemcrypto/odk/test/odk_test.cpp +++ b/oemcrypto/odk/test/odk_test.cpp @@ -863,6 +863,7 @@ std::vector TestCases() { // If the server is restricted to v16, then the response can be at // most 16.5 {16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5}, + {17, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 17, 6}, // Here are some known good versions. Make extra sure they work. {16, 16, 3, 16, 3}, {16, 16, 4, 16, 4}, @@ -876,6 +877,7 @@ std::vector TestCases() { {17, 17, 3, 17, 3}, {17, 17, 4, 17, 4}, {17, 17, 5, 17, 5}, + {17, 17, 6, 17, 6}, }; return test_cases; } diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h b/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h index 463a9c5..808eea5 100644 --- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h +++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h @@ -31,7 +31,7 @@ // version bumps to v17.1, the first released OPK implementation would be // v17.1.0 #define API_MAJOR_VERSION 17 -#define API_MINOR_VERSION 5 +#define API_MINOR_VERSION 6 #define OPK_PATCH_VERSION 0 #endif /* OEMCRYPTO_TA_OEMCRYPTO_API_MACROS_H_ */ diff --git a/oemcrypto/test/oec_decrypt_fallback_chain.cpp b/oemcrypto/test/oec_decrypt_fallback_chain.cpp index 0846b53..cbf552b 100644 --- a/oemcrypto/test/oec_decrypt_fallback_chain.cpp +++ b/oemcrypto/test/oec_decrypt_fallback_chain.cpp @@ -17,6 +17,7 @@ void advance_dest_buffer(OEMCrypto_DestBufferDesc* dest_buffer, size_t bytes) { switch (dest_buffer->type) { case OEMCrypto_BufferType_Clear: dest_buffer->buffer.clear.clear_buffer += bytes; + dest_buffer->buffer.clear.clear_buffer_length -= bytes; break; case OEMCrypto_BufferType_Secure: @@ -95,11 +96,6 @@ OEMCryptoResult DecryptFallbackChain::DecryptSample( const size_t length = subsample.num_bytes_clear + subsample.num_bytes_encrypted; fake_sample.buffers.input_data_length = length; - if (fake_sample.buffers.output_descriptor.type == - OEMCrypto_BufferType_Clear) { - fake_sample.buffers.output_descriptor.buffer.clear.clear_buffer_length = - length; - } fake_sample.subsamples = &subsample; fake_sample.subsamples_length = 1; @@ -142,11 +138,6 @@ OEMCryptoResult DecryptFallbackChain::DecryptSubsample( if (subsample.num_bytes_clear > 0) { fake_sample.buffers.input_data_length = subsample.num_bytes_clear; - if (fake_sample.buffers.output_descriptor.type == - OEMCrypto_BufferType_Clear) { - fake_sample.buffers.output_descriptor.buffer.clear.clear_buffer_length = - subsample.num_bytes_clear; - } fake_subsample.num_bytes_clear = subsample.num_bytes_clear; fake_subsample.num_bytes_encrypted = 0; fake_subsample.block_offset = 0; @@ -169,11 +160,6 @@ OEMCryptoResult DecryptFallbackChain::DecryptSubsample( if (subsample.num_bytes_encrypted > 0) { fake_sample.buffers.input_data_length = subsample.num_bytes_encrypted; - if (fake_sample.buffers.output_descriptor.type == - OEMCrypto_BufferType_Clear) { - fake_sample.buffers.output_descriptor.buffer.clear.clear_buffer_length = - subsample.num_bytes_encrypted; - } fake_subsample.num_bytes_clear = 0; fake_subsample.num_bytes_encrypted = subsample.num_bytes_encrypted; fake_subsample.block_offset = subsample.block_offset; diff --git a/oemcrypto/test/oemcrypto_test.cpp b/oemcrypto/test/oemcrypto_test.cpp index daf801c..89191fd 100644 --- a/oemcrypto/test/oemcrypto_test.cpp +++ b/oemcrypto/test/oemcrypto_test.cpp @@ -198,6 +198,106 @@ std::string MaybeHex(const uint8_t* data, size_t length) { std::string MaybeHex(const std::vector& data) { return MaybeHex(data.data(), data.size()); } + +const char* BoolName(bool value) { return value ? "true" : "false"; } +const char* SecurityLevelName(OEMCrypto_Security_Level value) { + switch (value) { + case OEMCrypto_Level_Unknown: + return "OEMCrypto_Level_Unknown"; + case OEMCrypto_Level1: + return "OEMCrypto_Level1"; + case OEMCrypto_Level2: + return "OEMCrypto_Level2"; + case OEMCrypto_Level3: + return "OEMCrypto_Level3"; + } + // Not reachable unless the enum value is invalid + return ""; +} +const char* HDCPCapabilityAsString(OEMCrypto_HDCP_Capability value) { + switch (value) { + case HDCP_NONE: + return "No HDCP supported, no secure data path"; + case HDCP_V1: + return "HDCP version 1.x"; + case HDCP_V1_0: + return "HDCP version 1.0"; + case HDCP_V1_1: + return "HDCP version 1.1"; + case HDCP_V1_2: + return "HDCP version 1.2"; + case HDCP_V1_3: + return "HDCP version 1.3"; + case HDCP_V1_4: + return "HDCP version 1.4"; + case HDCP_V2: + return "HDCP version 2.0"; + case HDCP_V2_1: + return "HDCP version 2.1"; + case HDCP_V2_2: + return "HDCP version 2.2"; + case HDCP_V2_3: + return "HDCP version 2.3"; + case HDCP_NO_DIGITAL_OUTPUT: + return "No HDCP device attached/using local display with secure path"; + } + // Not reachable unless the enum value is invalid + return ""; +} +const char* HDCPCapabilityName(OEMCrypto_HDCP_Capability value) { + switch (value) { + case HDCP_NONE: + return "HDCP_NONE"; + case HDCP_V1: + return "HDCP_V1"; + case HDCP_V1_0: + return "HDCP_V1_0"; + case HDCP_V1_1: + return "HDCP_V1_1"; + case HDCP_V1_2: + return "HDCP_V1_2"; + case HDCP_V1_3: + return "HDCP_V1_3"; + case HDCP_V1_4: + return "HDCP_V1_4"; + case HDCP_V2: + return "HDCP_V2"; + case HDCP_V2_1: + return "HDCP_V2_1"; + case HDCP_V2_2: + return "HDCP_V2_2"; + case HDCP_V2_3: + return "HDCP_V2_3"; + case HDCP_NO_DIGITAL_OUTPUT: + return "HDCP_NO_DIGITAL_OUTPUT"; + } + // Not reachable unless the enum value is invalid + return ""; +} +const char* WatermarkingSupportName(OEMCrypto_WatermarkingSupport value) { + switch (value) { + case OEMCrypto_WatermarkingError: + return "OEMCrypto_WatermarkingError"; + case OEMCrypto_WatermarkingNotSupported: + return "OEMCrypto_WatermarkingNotSupported"; + case OEMCrypto_WatermarkingConfigurable: + return "OEMCrypto_WatermarkingConfigurable"; + case OEMCrypto_WatermarkingAlwaysOn: + return "OEMCrypto_WatermarkingAlwaysOn"; + } + // Not reachable unless the enum value is invalid + return ""; +} +const char* DTCP2CapabiityName(OEMCrypto_DTCP2_Capability value) { + switch (value) { + case OEMCrypto_NO_DTCP2: + return "OEMCrypto_NO_DTCP2"; + case OEMCrypto_DTCP2_V1: + return "OEMCrypto_DTCP2_V1"; + } + // Not reachable unless the enum value is invalid + return ""; +} } // namespace class OEMCryptoClientTest : public ::testing::Test, public SessionUtil { @@ -269,6 +369,10 @@ class OEMCryptoClientTest : public ::testing::Test, public SessionUtil { return OEMCrypto_CopyBuffer(session, input_buffer, input_buffer_size, dest_buffer_descriptor, subsample_flags); } + + void RecordWvProperty(const std::string& key, const std::string& value) { + RecordProperty("widevine_metadata_oec_" + key, value); + } }; TEST_F(OEMCryptoClientTest, FreeUnallocatedSecureBufferNoFailure) { @@ -292,7 +396,7 @@ TEST_F(OEMCryptoClientTest, FreeUnallocatedSecureBufferNoFailure) { */ TEST_F(OEMCryptoClientTest, VersionNumber) { const std::string log_message = - "OEMCrypto unit tests for API 17.5. Tests last updated 2024-09-04"; + "OEMCrypto unit tests for API 17.6. Tests last updated 2024-11-04"; cout << " " << log_message << "\n"; cout << " " << "These tests are part of Android T." @@ -301,31 +405,45 @@ TEST_F(OEMCryptoClientTest, VersionNumber) { // If any of the following fail, then it is time to update the log message // above. EXPECT_EQ(ODK_MAJOR_VERSION, 17); - EXPECT_EQ(ODK_MINOR_VERSION, 5); + EXPECT_EQ(ODK_MINOR_VERSION, 6); EXPECT_EQ(kCurrentAPI, 17u); + RecordWvProperty("test_major_version", std::to_string(ODK_MAJOR_VERSION)); + RecordWvProperty("test_minor_version", std::to_string(ODK_MINOR_VERSION)); + OEMCrypto_Security_Level level = OEMCrypto_SecurityLevel(); EXPECT_GT(level, OEMCrypto_Level_Unknown); EXPECT_LE(level, OEMCrypto_Level3); cout << " OEMCrypto Security Level is L" << level << endl; + RecordWvProperty("security_level", SecurityLevelName(level)); + uint32_t version = OEMCrypto_APIVersion(); uint32_t minor_version = OEMCrypto_MinorAPIVersion(); cout << " OEMCrypto API version is " << version << "." << minor_version << endl; - if (OEMCrypto_SupportsUsageTable()) { + RecordWvProperty("major_version", std::to_string(version)); + RecordWvProperty("minor_version", std::to_string(minor_version)); + + const bool supports_usage_tables = OEMCrypto_SupportsUsageTable(); + if (supports_usage_tables) { cout << " OEMCrypto supports usage tables" << endl; } else { cout << " OEMCrypto does not support usage tables" << endl; } + RecordWvProperty("supports_usage_tables", BoolName(supports_usage_tables)); + if (version >= 15) { const uint32_t tier = OEMCrypto_ResourceRatingTier(); cout << " Resource Rating Tier: " << tier << endl; + RecordWvProperty("resource_rating_tier", std::to_string(tier)); } + if (version >= 17) { OEMCryptoResult sts = OEMCrypto_ProductionReady(); if (sts != OEMCrypto_SUCCESS) { LOGW("Device is not production ready, returns %d", sts); } - sts = OEMCrypto_SUCCESS; + RecordWvProperty("is_production_ready", BoolName(sts == OEMCrypto_SUCCESS)); + std::string build_info; size_t buf_length = 0; sts = OEMCrypto_BuildInformation(&build_info[0], &buf_length); @@ -338,9 +456,13 @@ TEST_F(OEMCryptoClientTest, VersionNumber) { build_info.resize(buf_length); } cout << " BuildInformation: " << build_info << endl; + RecordWvProperty("build_information", build_info); + OEMCrypto_WatermarkingSupport support = OEMCrypto_GetWatermarkingSupport(); cout << " WatermarkingSupport: " << support << endl; + RecordWvProperty("watermarking_support", WatermarkingSupportName(support)); } + ASSERT_GE(version, 8u); ASSERT_LE(version, kCurrentAPI); } @@ -461,42 +583,12 @@ TEST_F(OEMCryptoClientTest, ResourceRatingAPI15) { TEST_F(OEMCryptoClientTest, ProvisioningDeclaredAPI12) { OEMCrypto_ProvisioningMethod provisioning_method = OEMCrypto_GetProvisioningMethod(); - cout << " Provisioning method = " - << ProvisioningMethodName(provisioning_method) << endl; + const char* const name = ProvisioningMethodName(provisioning_method); + cout << " Provisioning method = " << name << endl; + RecordWvProperty("provisioning_method", name); ASSERT_NE(OEMCrypto_ProvisioningError, provisioning_method); } -const char* HDCPCapabilityAsString(OEMCrypto_HDCP_Capability value) { - switch (value) { - case HDCP_NONE: - return "No HDCP supported, no secure data path"; - case HDCP_V1: - return "HDCP version 1.x"; - case HDCP_V1_0: - return "HDCP version 1.0"; - case HDCP_V1_1: - return "HDCP version 1.1"; - case HDCP_V1_2: - return "HDCP version 1.2"; - case HDCP_V1_3: - return "HDCP version 1.3"; - case HDCP_V1_4: - return "HDCP version 1.4"; - case HDCP_V2: - return "HDCP version 2.0"; - case HDCP_V2_1: - return "HDCP version 2.1"; - case HDCP_V2_2: - return "HDCP version 2.2"; - case HDCP_V2_3: - return "HDCP version 2.3"; - case HDCP_NO_DIGITAL_OUTPUT: - return "No HDCP device attached/using local display with secure path"; - default: - return ""; - } -} - TEST_F(OEMCryptoClientTest, CheckHDCPCapabilityAPI09) { OEMCryptoResult sts; OEMCrypto_HDCP_Capability current, maximum; @@ -506,6 +598,8 @@ TEST_F(OEMCryptoClientTest, CheckHDCPCapabilityAPI09) { static_cast(current), HDCPCapabilityAsString(current)); printf(" Maximum HDCP Capability: 0x%02x = %s.\n", static_cast(maximum), HDCPCapabilityAsString(maximum)); + RecordWvProperty("hdcp_current", HDCPCapabilityName(current)); + RecordWvProperty("hdcp_max", HDCPCapabilityName(maximum)); } TEST_F(OEMCryptoClientTest, CheckSRMCapabilityV13) { @@ -514,11 +608,15 @@ TEST_F(OEMCryptoClientTest, CheckSRMCapabilityV13) { OEMCryptoResult current_result = OEMCrypto_GetCurrentSRMVersion(&version); if (current_result == OEMCrypto_SUCCESS) { printf(" Current SRM Version: %d.\n", version); + RecordWvProperty("srm_supported", BoolName(true)); + RecordWvProperty("srm_version", std::to_string(version)); EXPECT_NE(OEMCrypto_SUCCESS, OEMCrypto_GetCurrentSRMVersion(nullptr)); } else if (current_result == OEMCrypto_LOCAL_DISPLAY_ONLY) { printf(" Current SRM Status: Local Display Only.\n"); + RecordWvProperty("srm_supported", BoolName(false)); } else { EXPECT_EQ(OEMCrypto_ERROR_NOT_IMPLEMENTED, current_result); + RecordWvProperty("srm_supported", BoolName(false)); } } @@ -669,6 +767,7 @@ TEST_F(OEMCryptoClientTest, CheckMaxNumberOfSessionsAPI10) { OEMCryptoResult sts = OEMCrypto_GetMaxNumberOfSessions(&maximum); ASSERT_EQ(OEMCrypto_SUCCESS, sts); printf(" Max Number of Sessions: %zu.\n", maximum); + RecordWvProperty("max_number_of_sessions", std::to_string(maximum)); size_t required_max = GetResourceValue(kMaxConcurrentSession); ASSERT_GE(maximum, required_max); } @@ -676,6 +775,7 @@ TEST_F(OEMCryptoClientTest, CheckMaxNumberOfSessionsAPI10) { TEST_F(OEMCryptoClientTest, CheckUsageTableSizeAPI16) { const size_t maximum = OEMCrypto_MaximumUsageTableHeaderSize(); printf(" Max Usage Table Size: %zu.\n", maximum); + RecordWvProperty("max_usage_table_size", std::to_string(maximum)); // A maximum of 0 means the table is constrained by dynamic memory allocation. if (maximum > 0) { ASSERT_GE(maximum, RequiredUsageSize()); @@ -718,6 +818,7 @@ TEST_F(OEMCryptoClientTest, CheckDTCP2CapabilityAPI17) { "DTCP2 is supported.\n"); break; } + RecordWvProperty("dtcp2_capability", DTCP2CapabiityName(capability)); } // @@ -1185,6 +1286,7 @@ TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) { ASSERT_EQ(OEMCrypto_SUCCESS, sts); cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id, dev_id_len) << " len = " << dev_id_len << endl; + RecordWvProperty("device_id", wvutil::HexEncode(dev_id, dev_id_len)); } /** @ingroup security @@ -1226,8 +1328,12 @@ TEST_F(OEMCryptoKeyboxTest, NormalGetKeyData) { sts = OEMCrypto_GetKeyData(key_data, &key_data_len); uint32_t* data = reinterpret_cast(key_data); + const uint32_t system_id = htonl(data[1]); + const uint32_t version = htonl(data[0]); printf(" NormalGetKeyData: system_id = %u = 0x%04X, version=%u\n", - htonl(data[1]), htonl(data[1]), htonl(data[0])); + system_id, system_id, version); + RecordWvProperty("system_id", std::to_string(system_id)); + RecordWvProperty("key_data_version", std::to_string(version)); ASSERT_EQ(OEMCrypto_SUCCESS, sts); } @@ -1339,6 +1445,8 @@ TEST_F(OEMCryptoProv30Test, GetDeviceId) { dev_id.resize(dev_id_len); cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id) << " len = " << dev_id_len << endl; + RecordWvProperty("device_id", + wvutil::HexEncode(dev_id.data(), dev_id.size())); } // The OEM certificate must be valid. @@ -1735,6 +1843,8 @@ TEST_F(OEMCryptoProv40Test, GetDeviceId) { dev_id.resize(dev_id_len); cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id) << " len = " << dev_id_len << endl; + RecordWvProperty("device_id", + wvutil::HexEncode(dev_id.data(), dev_id.size())); // Device id should be stable. Query again. std::vector dev_id2(dev_id_len); sts = OEMCrypto_GetDeviceID(dev_id2.data(), &dev_id_len); @@ -4363,6 +4473,7 @@ TEST_P(OEMCryptoLicenseTest, MaxTotalKeysManySessions) { TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) { uint8_t patch_level = OEMCrypto_Security_Patch_Level(); printf(" Current Patch Level: %u.\n", patch_level); + RecordWvProperty("security_patch_level", std::to_string(patch_level)); { Session s; ASSERT_NO_FATAL_FAILURE(s.open());