Source release 18.5.0
This commit is contained in:
@@ -25,6 +25,11 @@ cc_library_static {
|
||||
"vendor/widevine/libwvdrmengine/oemcrypto/odk/include",
|
||||
"vendor/widevine/libwvdrmengine/oemcrypto/odk/src",
|
||||
],
|
||||
header_libs: [
|
||||
"jni_headers",
|
||||
"libbase_headers",
|
||||
"liblog_headers",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/odk.c",
|
||||
@@ -38,7 +43,7 @@ cc_library_static {
|
||||
proprietary: true,
|
||||
|
||||
owner: "widevine",
|
||||
min_sdk_version: "UpsideDownCake",
|
||||
min_sdk_version: "34",
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
@@ -51,6 +56,11 @@ cc_library_static {
|
||||
"vendor/widevine/libwvdrmengine/oemcrypto/odk/include",
|
||||
"vendor/widevine/libwvdrmengine/oemcrypto/odk/src",
|
||||
],
|
||||
header_libs: [
|
||||
"jni_headers",
|
||||
"libbase_headers",
|
||||
"liblog_headers",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/core_message_deserialize.cpp",
|
||||
|
||||
@@ -122,6 +122,7 @@ typedef enum OEMCrypto_Usage_Entry_Status {
|
||||
kInactiveUnused = 4,
|
||||
} OEMCrypto_Usage_Entry_Status;
|
||||
|
||||
/* Not used publicly. Not documented with Doxygen. */
|
||||
typedef enum OEMCrypto_ProvisioningRenewalType {
|
||||
OEMCrypto_NoRenewal = 0,
|
||||
OEMCrypto_RenewalACert = 1,
|
||||
@@ -137,7 +138,9 @@ typedef enum OEMCrypto_LicenseType {
|
||||
OEMCrypto_LicenseType_MaxValue = OEMCrypto_EntitlementLicense,
|
||||
} OEMCrypto_LicenseType;
|
||||
|
||||
/* Private key type used in the provisioning response. */
|
||||
/**
|
||||
* Private key type used in the provisioning response.
|
||||
*/
|
||||
typedef enum OEMCrypto_PrivateKeyType {
|
||||
OEMCrypto_RSA_Private_Key = 0,
|
||||
OEMCrypto_ECC_Private_Key = 1,
|
||||
|
||||
@@ -26,9 +26,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 18.2.
|
||||
// number. The default is 18.5.
|
||||
uint32_t maximum_major_version = 18;
|
||||
uint32_t maximum_minor_version = 2;
|
||||
uint32_t maximum_minor_version = 5;
|
||||
|
||||
bool operator==(const CoreMessageFeatures &other) const;
|
||||
bool operator!=(const CoreMessageFeatures &other) const {
|
||||
|
||||
@@ -16,10 +16,10 @@ extern "C" {
|
||||
|
||||
/* The version of this library. */
|
||||
#define ODK_MAJOR_VERSION 18
|
||||
#define ODK_MINOR_VERSION 2
|
||||
#define ODK_MINOR_VERSION 5
|
||||
|
||||
/* ODK Version string. Date changed automatically on each release. */
|
||||
#define ODK_RELEASE_DATE "ODK v18.2 2023-06-14"
|
||||
#define ODK_RELEASE_DATE "ODK v18.5 2024-03-21"
|
||||
|
||||
/* The lowest version number for an ODK message. */
|
||||
#define ODK_FIRST_VERSION 16
|
||||
|
||||
@@ -19,7 +19,9 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
|
||||
uint32_t maximum_major_version) {
|
||||
CoreMessageFeatures features;
|
||||
features.maximum_major_version = maximum_major_version;
|
||||
// The default minor version is the highest for each major version.
|
||||
// The default minor version is the highest for each major version. This also
|
||||
// needs to be updated with new version releases in
|
||||
// ODK_InitializeSessionValues() when the minor version is being set.
|
||||
switch (maximum_major_version) {
|
||||
case 16:
|
||||
features.maximum_minor_version = 5; // 16.5
|
||||
@@ -28,7 +30,7 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
|
||||
features.maximum_minor_version = 2; // 17.2
|
||||
break;
|
||||
case 18:
|
||||
features.maximum_minor_version = 2; // 18.2
|
||||
features.maximum_minor_version = 5; // 18.5
|
||||
break;
|
||||
default:
|
||||
features.maximum_minor_version = 0;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odk_message.h"
|
||||
#include "odk_overflow.h"
|
||||
#include "odk_serialize.h"
|
||||
#include "odk_structs.h"
|
||||
@@ -45,12 +46,23 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
* message buffer has been correctly initialized by the caller. */
|
||||
switch (message_type) {
|
||||
case ODK_License_Request_Type: {
|
||||
core_message->message_length = ODK_LICENSE_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedLicenseRequest) > prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
if (nonce_values->api_major_version > 17) {
|
||||
core_message->message_length = ODK_LICENSE_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedLicenseRequest) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedLicenseRequest(
|
||||
&msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
} else {
|
||||
core_message->message_length = ODK_LICENSE_REQUEST_SIZE_V17;
|
||||
if (sizeof(ODK_PreparedLicenseRequestV17) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedLicenseRequestV17(
|
||||
&msg, (ODK_PreparedLicenseRequestV17*)prepared_request_buffer);
|
||||
}
|
||||
Pack_ODK_PreparedLicenseRequest(
|
||||
&msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewal_Request_Type: {
|
||||
@@ -63,13 +75,23 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning_Request_Type: {
|
||||
core_message->message_length = ODK_PROVISIONING_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedProvisioningRequest) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
if (nonce_values->api_major_version > 17) {
|
||||
core_message->message_length = ODK_PROVISIONING_REQUEST_SIZE;
|
||||
if (sizeof(ODK_PreparedProvisioningRequest) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedProvisioningRequest(
|
||||
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
} else {
|
||||
core_message->message_length = ODK_PROVISIONING_REQUEST_SIZE_V17;
|
||||
if (sizeof(ODK_PreparedProvisioningRequestV17) >
|
||||
prepared_request_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedProvisioningRequestV17(
|
||||
&msg, (ODK_PreparedProvisioningRequestV17*)prepared_request_buffer);
|
||||
}
|
||||
Pack_ODK_PreparedProvisioningRequest(
|
||||
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning40_Request_Type: {
|
||||
@@ -186,12 +208,19 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
counter_info == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedLicenseRequest license_request = {0};
|
||||
memcpy(&license_request.counter_info, counter_info,
|
||||
sizeof(license_request.counter_info));
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_size, ODK_License_Request_Type,
|
||||
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
|
||||
if (nonce_values->api_major_version > 17) {
|
||||
ODK_PreparedLicenseRequest license_request = {0};
|
||||
memcpy(&license_request.counter_info, counter_info,
|
||||
sizeof(license_request.counter_info));
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_size, ODK_License_Request_Type,
|
||||
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
|
||||
} else {
|
||||
ODK_PreparedLicenseRequestV17 license_request = {0};
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_size, ODK_License_Request_Type,
|
||||
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequestV17));
|
||||
}
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
@@ -250,14 +279,22 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
counter_info == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedProvisioningRequest provisioning_request = {0};
|
||||
memcpy(&provisioning_request.counter_info, counter_info,
|
||||
sizeof(ODK_MessageCounterInfo));
|
||||
if (nonce_values->api_major_version > 17) {
|
||||
ODK_PreparedProvisioningRequest provisioning_request = {0};
|
||||
memcpy(&provisioning_request.counter_info, counter_info,
|
||||
sizeof(ODK_MessageCounterInfo));
|
||||
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Request_Type, nonce_values,
|
||||
&provisioning_request,
|
||||
sizeof(ODK_PreparedProvisioningRequest));
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Request_Type, nonce_values,
|
||||
&provisioning_request,
|
||||
sizeof(ODK_PreparedProvisioningRequest));
|
||||
} else {
|
||||
ODK_PreparedProvisioningRequestV17 provisioning_request = {0};
|
||||
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||
ODK_Provisioning_Request_Type, nonce_values,
|
||||
&provisioning_request,
|
||||
sizeof(ODK_PreparedProvisioningRequestV17));
|
||||
}
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_PrepareCoreProvisioning40Request(
|
||||
@@ -434,10 +471,14 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
*/
|
||||
/* If a renewal request is lost in transit, we should throw it out and create
|
||||
* a new one. We use the timestamp to make sure we have the latest request.
|
||||
* We only do this if playback has already started. This allows us to reload
|
||||
* an offline license and also reload a renewal before starting playback.
|
||||
* We only do this if a renewal has been requested for this session. This
|
||||
* allows us to reload an offline license and also reload a renewal from a
|
||||
* previous session before starting playback.
|
||||
* TODO: b/290249855 - This is reversed. It should be "!=" instead of "<".
|
||||
* We will not fix this in the current release, because it is already in
|
||||
* production code. Instead, this will be fixed in v19.
|
||||
*/
|
||||
if (clock_values->timer_status != ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED &&
|
||||
if (clock_values->time_of_renewal_request > 0 &&
|
||||
clock_values->time_of_renewal_request <
|
||||
renewal_response.request.playback_time) {
|
||||
return ODK_STALE_RENEWAL;
|
||||
@@ -489,14 +530,6 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
const uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||
/* check bytes beyond device_id_length are 0 */
|
||||
if (crypto_memcmp(
|
||||
zero, provisioning_response.request.device_id + device_id_length,
|
||||
ODK_DEVICE_ID_LEN_MAX - device_id_length) != 0) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
} else {
|
||||
// v18
|
||||
ODK_ProvisioningResponse provisioning_response = {0};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (__STDC_VERSION__ >= 201112L)
|
||||
#if defined(_MSC_VER) || (__STDC_VERSION__ >= 201112L)
|
||||
#include <assert.h>
|
||||
#define odk_static_assert static_assert
|
||||
#else
|
||||
|
||||
@@ -123,8 +123,10 @@ typedef struct {
|
||||
// ../test/odk_test.cpp for validations of each of the defined request sizes.
|
||||
#define ODK_CORE_MESSAGE_SIZE 20u
|
||||
#define ODK_LICENSE_REQUEST_SIZE 90u
|
||||
#define ODK_LICENSE_REQUEST_SIZE_V17 20u
|
||||
#define ODK_RENEWAL_REQUEST_SIZE 28u
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE 94u
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE_V17 88u
|
||||
#define ODK_PROVISIONING40_REQUEST_SIZE 862u
|
||||
#define ODK_RENEWED_PROVISIONING_REQUEST_SIZE 1694u
|
||||
#define ODK_MESSAGECOUNTERINFO_SIZE 70u
|
||||
|
||||
@@ -254,11 +254,6 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
|
||||
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
/* Check that the API version passed in from OEMCrypto matches the version of
|
||||
* this ODK library. */
|
||||
if (api_major_version != ODK_MAJOR_VERSION) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
timer_limits->soft_enforce_rental_duration = false;
|
||||
timer_limits->soft_enforce_playback_duration = false;
|
||||
timer_limits->earliest_playback_start_seconds = 0;
|
||||
@@ -268,8 +263,23 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
|
||||
|
||||
ODK_InitializeClockValues(clock_values, 0);
|
||||
|
||||
nonce_values->api_major_version = ODK_MAJOR_VERSION;
|
||||
nonce_values->api_minor_version = ODK_MINOR_VERSION;
|
||||
nonce_values->api_major_version = api_major_version;
|
||||
// This needs to be updated with new version releases in the default features
|
||||
// of core message features.
|
||||
switch (nonce_values->api_major_version) {
|
||||
case 16:
|
||||
nonce_values->api_minor_version = 5;
|
||||
break;
|
||||
case 17:
|
||||
nonce_values->api_minor_version = 2;
|
||||
break;
|
||||
case 18:
|
||||
nonce_values->api_minor_version = 5;
|
||||
break;
|
||||
default:
|
||||
nonce_values->api_minor_version = 0;
|
||||
break;
|
||||
}
|
||||
nonce_values->nonce = 0;
|
||||
nonce_values->session_id = session_id;
|
||||
|
||||
@@ -300,6 +310,7 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
||||
clock_values->time_of_license_request_signed = system_time_seconds;
|
||||
clock_values->time_of_first_decrypt = 0;
|
||||
clock_values->time_of_last_decrypt = 0;
|
||||
clock_values->time_of_renewal_request = 0;
|
||||
clock_values->time_when_timer_expires = 0;
|
||||
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED;
|
||||
clock_values->status = kUnused;
|
||||
|
||||
@@ -334,12 +334,21 @@ TEST(OdkTest, NullRequestTest) {
|
||||
&nonce_values, nullptr, 0uL, nullptr));
|
||||
|
||||
// Null device id in provisioning request is ok
|
||||
uint8_t message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||
core_message_length = ODK_PROVISIONING_REQUEST_SIZE;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
ODK_PrepareCoreProvisioningRequest(
|
||||
message, ODK_PROVISIONING_REQUEST_SIZE, &core_message_length,
|
||||
&nonce_values, &counter_info));
|
||||
if (nonce_values.api_major_version > 17) {
|
||||
uint8_t message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||
core_message_length = ODK_PROVISIONING_REQUEST_SIZE;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
ODK_PrepareCoreProvisioningRequest(
|
||||
message, ODK_PROVISIONING_REQUEST_SIZE, &core_message_length,
|
||||
&nonce_values, &counter_info));
|
||||
} else {
|
||||
uint8_t message[ODK_PROVISIONING_REQUEST_SIZE_V17] = {0};
|
||||
core_message_length = ODK_PROVISIONING_REQUEST_SIZE_V17;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
ODK_PrepareCoreProvisioningRequest(
|
||||
message, ODK_PROVISIONING_REQUEST_SIZE_V17,
|
||||
&core_message_length, &nonce_values, &counter_info));
|
||||
}
|
||||
|
||||
// Null device info in provisioning 4.0 request is ok
|
||||
uint8_t message_prov4[ODK_PROVISIONING40_REQUEST_SIZE] = {0};
|
||||
@@ -885,7 +894,10 @@ TEST(OdkTest, ParseRenewalErrorTimer) {
|
||||
uint32_t buf_size = 0;
|
||||
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||
&buf_size);
|
||||
params.clock_values.time_of_renewal_request = 0;
|
||||
// Set the time for the last renewal request, as seen in clock_values, to be
|
||||
// after the time in the request.
|
||||
// TODO: b/290249855 - This is reversed. It should be +5.
|
||||
params.clock_values.time_of_renewal_request = params.playback_clock - 5;
|
||||
OEMCryptoResult err = ODK_ParseRenewal(
|
||||
buf, buf_size, buf_size, &(params.core_message.nonce_values),
|
||||
params.system_time, &(params.timer_limits), &(params.clock_values),
|
||||
@@ -1204,7 +1216,7 @@ std::vector<VersionParameters> TestCases() {
|
||||
// number.
|
||||
{16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5},
|
||||
{17, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 17, 2},
|
||||
{18, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 18, 2},
|
||||
{18, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 18, 5},
|
||||
// Here are some known good versions. Make extra sure they work.
|
||||
{ODK_MAJOR_VERSION, 16, 3, 16, 3},
|
||||
{ODK_MAJOR_VERSION, 16, 4, 16, 4},
|
||||
@@ -1213,12 +1225,16 @@ std::vector<VersionParameters> TestCases() {
|
||||
{ODK_MAJOR_VERSION, 17, 2, 17, 2},
|
||||
{ODK_MAJOR_VERSION, 18, 1, 18, 1},
|
||||
{ODK_MAJOR_VERSION, 18, 2, 18, 2},
|
||||
{ODK_MAJOR_VERSION, 18, 3, 18, 3},
|
||||
{ODK_MAJOR_VERSION, 18, 4, 18, 4},
|
||||
{ODK_MAJOR_VERSION, 18, 5, 18, 5},
|
||||
{0, 16, 3, 16, 3},
|
||||
{0, 16, 4, 16, 4},
|
||||
{0, 16, 5, 16, 5},
|
||||
{0, 17, 1, 17, 1},
|
||||
{0, 17, 2, 17, 2},
|
||||
{0, 18, 2, 18, 2}, // Change to 19 when the default version is updated.
|
||||
{0, 18, 4, 18, 4},
|
||||
{0, 18, 5, 18, 5},
|
||||
};
|
||||
return test_cases;
|
||||
}
|
||||
@@ -1243,7 +1259,11 @@ TEST(OdkSizeTest, LicenseRequest) {
|
||||
&core_message_length, &nonce_values,
|
||||
&counter_info));
|
||||
// the core_message_length should be appropriately set
|
||||
EXPECT_EQ(ODK_LICENSE_REQUEST_SIZE, core_message_length);
|
||||
if (nonce_values.api_major_version > 17) {
|
||||
EXPECT_EQ(ODK_LICENSE_REQUEST_SIZE, core_message_length);
|
||||
} else {
|
||||
EXPECT_EQ(ODK_LICENSE_REQUEST_SIZE_V17, core_message_length);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OdkSizeTest, RenewalRequest) {
|
||||
@@ -1307,7 +1327,11 @@ TEST(OdkSizeTest, ProvisioningRequest) {
|
||||
&core_message_length,
|
||||
&nonce_values, &counter_info));
|
||||
// the core_message_length should be appropriately set
|
||||
EXPECT_EQ(ODK_PROVISIONING_REQUEST_SIZE, core_message_length);
|
||||
if (nonce_values.api_major_version > 17) {
|
||||
EXPECT_EQ(ODK_PROVISIONING_REQUEST_SIZE, core_message_length);
|
||||
} else {
|
||||
EXPECT_EQ(ODK_PROVISIONING_REQUEST_SIZE_V17, core_message_length);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the version string contains the right version numbers.
|
||||
|
||||
Reference in New Issue
Block a user