Source release 18.5.0

This commit is contained in:
Matt Feddersen
2024-03-28 19:15:22 -07:00
parent b2c35151ad
commit 28ec8548c6
109 changed files with 3623 additions and 1012 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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