OEMCrypto and OPK 17.6

This commit is contained in:
Vicky Min
2024-11-26 20:46:31 +00:00
parent cca31312fe
commit 56266e3cdd
10 changed files with 169 additions and 61 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -863,6 +863,7 @@ std::vector<VersionParameters> 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<VersionParameters> TestCases() {
{17, 17, 3, 17, 3},
{17, 17, 4, 17, 4},
{17, 17, 5, 17, 5},
{17, 17, 6, 17, 6},
};
return test_cases;
}

View File

@@ -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_ */

View File

@@ -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;

View File

@@ -198,6 +198,106 @@ std::string MaybeHex(const uint8_t* data, size_t length) {
std::string MaybeHex(const std::vector<uint8_t>& 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 "<INVALID VALUE>";
}
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 "<INVALID VALUE>";
}
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 "<INVALID VALUE>";
}
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 "<INVALID VALUE>";
}
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 "<INVALID VALUE>";
}
} // 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 "<INVALID VALUE>";
}
}
TEST_F(OEMCryptoClientTest, CheckHDCPCapabilityAPI09) {
OEMCryptoResult sts;
OEMCrypto_HDCP_Capability current, maximum;
@@ -506,6 +598,8 @@ TEST_F(OEMCryptoClientTest, CheckHDCPCapabilityAPI09) {
static_cast<unsigned int>(current), HDCPCapabilityAsString(current));
printf(" Maximum HDCP Capability: 0x%02x = %s.\n",
static_cast<unsigned int>(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<uint32_t*>(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<uint8_t> 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());