Automated update of OPK code

Included changes:

  - 92a0538dc60ad0c48866b5736fcec125f6493d8d Remove unused function by John "Juce" Bruce <juce@google.com>
  - 7235e2c89a94d6b6ed086aa83cd4b22b56bd8d65 Various static function fixes by John "Juce" Bruce <juce@google.com>
  - 908055030aa283ce74915fb68571b0ce3854e12e Fix duplicate & missing headers identified by clang-tidy by John "Juce" Bruce <juce@google.com>
  - 502b8b8caeb4654f294398039fff98ec641bda24 Updated `core_message_features.cpp` to use `odk_versions.h` by Alex Dale <sigquit@google.com>
  - 3163312183f5e0b8a08b97cfe171221861743cc5 Bump ODK max supported minor versions by Matt Feddersen <mattfedd@google.com>
  - c461df67a9003e738042716ae644dd96a66d2446 Updated ODK minor versions for 2025Q2 release. by Alex Dale <sigquit@google.com>
  - 56a43e881c31e4e2d3a2a7732bef00705a252a65 Added ODK_InitializeSessionValuesEx by Alex Dale <sigquit@google.com>

GitOrigin-RevId: 92a0538dc60ad0c48866b5736fcec125f6493d8d
This commit is contained in:
Googler
2025-04-21 22:41:04 +00:00
committed by mattfedd
parent 5387878a5b
commit c56808c463
18 changed files with 207 additions and 91 deletions

View File

@@ -38,9 +38,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 19.5.
// number. The default is 19.6.
uint32_t maximum_major_version = 19;
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

@@ -98,6 +98,36 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
uint32_t api_major_version,
uint32_t session_id);
/*
* This function initializes the session's data structures. It shall be
* called from OEMCrypto_OpenSession.
*
* This function is an extended "Ex" version of
* ODK_InitializeSessionValues(). It is not intended for production systems;
* ODK_InitializeSessionValues() should be used instead.
*
* This function is intentionally excluded from Doxygen.
*
* @param[out] timer_limits: the session's timer limits.
* @param[out] clock_values: the session's clock values.
* @param[out] nonce_values: the session's ODK nonce values.
* @param[in] api_major_version: the API major version of OEMCrypto.
* @param[in] api_minor_version: the API minor version of OEMCrypto.
* @param[in] session_id: the session id of the newly created session.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
* This method is new in version 20.0 of the API.
*/
OEMCryptoResult ODK_InitializeSessionValuesEx(ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t api_minor_version,
uint32_t session_id);
/**
* This function sets the nonce value in the session's nonce structure. It
* shall be called from OEMCrypto_GenerateNonce.

View File

@@ -19,7 +19,7 @@ extern "C" {
#define ODK_MINOR_VERSION 0
/* ODK Version string. Date changed automatically on each release. */
#define ODK_RELEASE_DATE "ODK v20.0 2025-05-20"
#define ODK_RELEASE_DATE "ODK v20.0 2025-06-05"
/* The lowest version number for an ODK message. */
#define ODK_FIRST_VERSION 16

View File

@@ -12,13 +12,14 @@
#include <utility>
#include "odk_structs.h"
#include "odk_versions.h"
namespace oemcrypto_core_message {
namespace features {
namespace {
// The first major version where we decided to prerelease a test version the ODK
// library.
constexpr int kFirstPrereleaseVersion = 20;
constexpr uint32_t kFirstPrereleaseVersion = 20;
} // namespace
const CoreMessageFeatures CoreMessageFeatures::kDefaultFeatures;
@@ -37,19 +38,19 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
// ODK_InitializeSessionValues() when the minor version is being set.
switch (maximum_major_version) {
case 16:
features.maximum_minor_version = 5; // 16.5
features.maximum_minor_version = ODK_V16_MINOR_VERSION;
break;
case 17:
features.maximum_minor_version = 2; // 17.2
features.maximum_minor_version = ODK_V17_MINOR_VERSION;
break;
case 18:
features.maximum_minor_version = 4; // 18.4
features.maximum_minor_version = ODK_V18_MINOR_VERSION;
break;
case 19:
features.maximum_minor_version = 2; // 19.2
features.maximum_minor_version = ODK_V19_MINOR_VERSION;
break;
case 20:
features.maximum_minor_version = 0; // 20.0
features.maximum_minor_version = ODK_V20_MINOR_VERSION;
break;
default:
features.maximum_minor_version = 0;

View File

@@ -3,7 +3,6 @@
// License Agreement.
#include <stdint.h>
#include <string.h>
#include "OEMCryptoCENCCommon.h"
#include "odk.h"
@@ -11,6 +10,11 @@
#include "odk_overflow.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
#include "odk_versions.h"
/* This is a special value used to signal that the latest API
* minor version should be used for a particular API major version. */
#define ODK_LATEST_API_MINOR_VERSION UINT32_MAX
/* Private function. Checks to see if the license is active. Returns
* ODK_TIMER_EXPIRED if the license is valid but inactive. Returns
@@ -243,6 +247,64 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
return ODK_SET_TIMER;
}
/* Private function. Initialize the timer limits to default values. */
static void InitializeTimerLimits(ODK_TimerLimits* timer_limits) {
if (timer_limits == NULL) {
return;
}
timer_limits->soft_enforce_rental_duration = false;
timer_limits->soft_enforce_playback_duration = false;
timer_limits->earliest_playback_start_seconds = 0;
timer_limits->rental_duration_seconds = 0;
timer_limits->total_playback_duration_seconds = 0;
timer_limits->initial_renewal_duration_seconds = 0;
}
/* Private function. Obtains the maximum minor version for a given major
* version. */
static uint32_t GetApiMinorVersion(uint32_t api_major_version) {
/* This needs to be updated with new major version releases. */
switch (api_major_version) {
case 16:
return ODK_V16_MINOR_VERSION;
case 17:
return ODK_V17_MINOR_VERSION;
case 18:
return ODK_V18_MINOR_VERSION;
case 19:
return ODK_V19_MINOR_VERSION;
case 20:
return ODK_V20_MINOR_VERSION;
default:
return 0;
}
}
/* Private function. Initialize the nonce values.
* Note: |api_minor_version| may be set to ODK_LATEST_API_MINOR_VERSION.*/
static void InitializeNonceValues(ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t api_minor_version,
uint32_t session_id) {
if (nonce_values == NULL) {
return;
}
if (api_major_version > ODK_MAJOR_VERSION) {
api_major_version = ODK_MAJOR_VERSION;
}
/* Floor the API minor version to the maximum minor version for the API major
* version. */
const uint32_t max_api_minor_version = GetApiMinorVersion(api_major_version);
if (api_minor_version > max_api_minor_version) {
api_minor_version = max_api_minor_version;
}
nonce_values->api_major_version = api_major_version;
nonce_values->api_minor_version = api_minor_version;
nonce_values->nonce = 0;
nonce_values->session_id = session_id;
}
/************************************************************************/
/************************************************************************/
/* Public functions, declared in odk.h. */
@@ -256,41 +318,27 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
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;
timer_limits->rental_duration_seconds = 0;
timer_limits->total_playback_duration_seconds = 0;
timer_limits->initial_renewal_duration_seconds = 0;
InitializeTimerLimits(timer_limits);
ODK_InitializeClockValues(clock_values, 0);
InitializeNonceValues(nonce_values, api_major_version,
ODK_LATEST_API_MINOR_VERSION, session_id);
return OEMCrypto_SUCCESS;
}
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 = 7;
break;
case 18:
nonce_values->api_minor_version = 9;
break;
case 19:
nonce_values->api_minor_version = 5;
break;
case ODK_MAJOR_VERSION:
nonce_values->api_minor_version = ODK_MINOR_VERSION;
break;
default:
nonce_values->api_minor_version = 0;
break;
/* This is called when certain OEMCrypto implementations opens a new session. */
OEMCryptoResult ODK_InitializeSessionValuesEx(ODK_TimerLimits* timer_limits,
ODK_ClockValues* clock_values,
ODK_NonceValues* nonce_values,
uint32_t api_major_version,
uint32_t api_minor_version,
uint32_t session_id) {
if (timer_limits == NULL || clock_values == NULL || nonce_values == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
nonce_values->nonce = 0;
nonce_values->session_id = session_id;
InitializeTimerLimits(timer_limits);
ODK_InitializeClockValues(clock_values, 0);
InitializeNonceValues(nonce_values, api_major_version, api_minor_version,
session_id);
return OEMCrypto_SUCCESS;
}

View File

@@ -0,0 +1,25 @@
// Copyright 2025 Google LLC. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
#ifndef WIDEVINE_ODK_SRC_ODK_VERSIONS_H_
#define WIDEVINE_ODK_SRC_ODK_VERSIONS_H_
#include <stdint.h>
#include "odk_structs.h"
/* Highest ODK minor version number by major version. */
#define ODK_V16_MINOR_VERSION 5
#define ODK_V17_MINOR_VERSION 8
#define ODK_V18_MINOR_VERSION 10
#define ODK_V19_MINOR_VERSION 6
/* Whenever the next major version is released, this should be updated to the
* new major version. */
#if ODK_MAJOR_VERSION != 20
#error "ODK_MAJOR_VERSION has changed. Please update this file."
#endif
#define ODK_V20_MINOR_VERSION ODK_MINOR_VERSION
#endif // WIDEVINE_ODK_SRC_ODK_VERSIONS_H_

View File

@@ -1377,9 +1377,9 @@ std::vector<VersionParameters> TestCases() {
CoreMessageFeatures::kDefaultFeatures.maximum_major_version,
CoreMessageFeatures::kDefaultFeatures.maximum_minor_version);
const VersionPair v16(16, 5);
const VersionPair v17(17, 6);
const VersionPair v18(18, 8);
const VersionPair v19(19, 5);
const VersionPair v17(17, 8);
const VersionPair v18(18, 10);
const VersionPair v19(19, 6);
const VersionPair v20_prerelease(20, 0);
const VersionPair v20(20, 1);

View File

@@ -36,6 +36,6 @@
#define API_MAJOR_VERSION 20
#define API_MINOR_VERSION 0
#define OPK_PATCH_VERSION 0
#define OPK_BUILD_ID "2025-05-30"
#define OPK_BUILD_ID "2025-06-06"
#endif /* OEMCRYPTO_TA_OEMCRYPTO_API_MACROS_H_ */

View File

@@ -87,6 +87,7 @@ void print_cbor(cn_cbor* cn, uint32_t type) {
}
namespace wtpi_test {
namespace {
// Copied and modified from open-dice test_utils.cc
ScopedCbor ExtractCwtFromCborCertificate(const uint8_t* certificate,
size_t certificate_size) {
@@ -157,6 +158,7 @@ ScopedCbor ExtractPublicKeyFromCwt(const cn_cbor* cwt) {
}
return key;
}
} // namespace
ScopedCbor ExtractPublicKeyFromBcc(const uint8_t* bytes, size_t bytes_len) {
// Get bcc payload, which is a CBOR Web Token.

View File

@@ -16,6 +16,8 @@
#include "wtpi_device_key_interface.h"
#define UUID_LENGTH 16
namespace {
// This struct represents a wrapped blob that we do not yet know how to
// interpret. It contains only the fields that we expect every versioned blob to
// have.
@@ -27,11 +29,11 @@ typedef struct WrappedData {
} WrappedData;
// The randomly-generated UUID that identifies a blob as a WrappedData struct,
// in network byte order.
static const uint8_t kMagicUuid[UUID_LENGTH] = {
0xb5, 0x76, 0x3b, 0xad, 0x84, 0x05, 0x40, 0xfd,
0xa0, 0x88, 0x3b, 0x6c, 0x69, 0x97, 0xfc, 0x74};
const uint8_t kMagicUuid[UUID_LENGTH] = {0xb5, 0x76, 0x3b, 0xad, 0x84, 0x05,
0x40, 0xfd, 0xa0, 0x88, 0x3b, 0x6c,
0x69, 0x97, 0xfc, 0x74};
// 1 in network byte order
static const uint8_t kVersionOne[sizeof(uint32_t)] = {0x00, 0x00, 0x00, 0x01};
const uint8_t kVersionOne[sizeof(uint32_t)] = {0x00, 0x00, 0x00, 0x01};
// This is the layout of the |data| field of a WrappedData structure when its
// |version| field is 1.
typedef struct WrappedData_V1 {
@@ -39,15 +41,15 @@ typedef struct WrappedData_V1 {
uint8_t enc_data[];
} WrappedData_V1;
static OEMCryptoResult GetEncryptAndSignSize(uint32_t context, size_t in_size,
size_t* wrapped_size) {
OEMCryptoResult GetEncryptAndSignSize(uint32_t context, size_t in_size,
size_t* wrapped_size) {
*wrapped_size = in_size + sizeof(WrappedData) + sizeof(WrappedData_V1);
return OEMCrypto_SUCCESS;
}
OEMCryptoResult EncryptAndSign_V1(uint32_t context, const uint8_t* data,
size_t data_size, uint8_t* out,
size_t* out_size) {
size_t data_size, uint8_t* out,
size_t* out_size) {
if (!out_size) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -91,6 +93,7 @@ OEMCryptoResult EncryptAndSign_V1(uint32_t context, const uint8_t* data,
WTPI_K1_FreeKeyHandle(signing_key);
return result;
}
} // namespace
class LegacyKeywrapTest : public ::testing::Test {
protected:

View File

@@ -7,6 +7,7 @@
#include "log.h"
namespace {
void dump_ssl_error(void) {
int count = 0;
unsigned long err;
@@ -17,6 +18,7 @@ void dump_ssl_error(void) {
LOGE("SSL Error %d -- %lu -- %s", count, err, buffer);
}
}
} // namespace
bool DeserializePKCS8PrivateKey(const uint8_t* serialized_bytes, size_t size,
RSA** rsa) {

View File

@@ -12,7 +12,10 @@
* This is a PKCS8 RSA key encoded in DER format.
*/
#include "stdint.h"
#include "test_common.h"
#include <stdint.h>
uint8_t test_rsa_key_der[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,

View File

@@ -9,6 +9,8 @@
// posix_services.h implementation of semaphores and shared memory
// which is based on the POSIX shared memory and semaphore libraries.
#include "tos_transport.h"
#include "odk_message.h"
#include "posix_resources.h"
#include "tos_transport_interface.h"
@@ -20,19 +22,20 @@
using namespace posix;
namespace {
// message request/response payload data
static RequestResponseBlock* shared_memory_ = nullptr;
RequestResponseBlock* shared_memory_ = nullptr;
// mailbox containing the size of the payload
static MailboxBlock* mailbox_memory_ = nullptr;
MailboxBlock* mailbox_memory_ = nullptr;
// post when a request message is ready
static RequestSemaphore* request_semaphore_ = nullptr;
RequestSemaphore* request_semaphore_ = nullptr;
// post when a response message is ready
static ResponseSemaphore* response_semaphore_ = nullptr;
ResponseSemaphore* response_semaphore_ = nullptr;
static void ReleaseResources() {
void ReleaseResources() {
if (shared_memory_) {
delete shared_memory_;
shared_memory_ = nullptr;
@@ -51,6 +54,25 @@ static void ReleaseResources() {
}
}
// Get the size of the message from the mailbox and return it
uint32_t PeekSize(void) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
uint32_t message_size = (uint32_t)mailbox[0] | (uint32_t)mailbox[1] << 8 |
(uint32_t)mailbox[2] << 16 |
(uint32_t)mailbox[3] << 24;
return message_size;
}
// Put the size of the message into the mailbox
void PokeSize(uint32_t size) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
mailbox[0] = (uint8_t)(size);
mailbox[1] = (uint8_t)(size >> 8);
mailbox[2] = (uint8_t)(size >> 16);
mailbox[3] = (uint8_t)(size >> 24);
}
} // namespace
bool TOS_Transport_Initialize(void) {
if (!(shared_memory_ = new RequestResponseBlock()) ||
!(shared_memory_->Allocate(OPK_TRANSPORT_MESSAGE_SIZE))) {
@@ -94,24 +116,6 @@ void TOS_Transport_ReleaseMessage(ODK_Message* message) {
(void)message;
}
// Get the size of the message from the mailbox and return it
static uint32_t PeekSize(void) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
uint32_t message_size = (uint32_t)mailbox[0] | (uint32_t)mailbox[1] << 8 |
(uint32_t)mailbox[2] << 16 |
(uint32_t)mailbox[3] << 24;
return message_size;
}
// Put the size of the message into the mailbox
static void PokeSize(uint32_t size) {
uint8_t* mailbox = mailbox_memory_->GetAddress();
mailbox[0] = (uint8_t)(size);
mailbox[1] = (uint8_t)(size >> 8);
mailbox[2] = (uint8_t)(size >> 16);
mailbox[3] = (uint8_t)(size >> 24);
}
// The request has been packed into the shared memory, all we need to
// do is poke the message size in the mailbox and post on the request
// semaphore, then wait for the response semaphore. The response will

View File

@@ -19,6 +19,7 @@
static pthread_t main_thread_tid;
static bool thread_running = false;
namespace {
void signalHandler(int signum) {
(void)signum;
// TODO(fredgc): this doesn't actually kill anything because the main loop is
@@ -27,6 +28,7 @@ void signalHandler(int signum) {
// This exits, but then we skip the OPK_Terminate call.
exit(0);
}
} // namespace
// The request message data must be copied into a local buffer
// so the contents can't be modified while being parsed.

View File

@@ -9,7 +9,9 @@
#include "oemcrypto_corpus_generator_helper.h"
#include "test_sleep.h"
static void acknowledge_cast() {
namespace {
void acknowledge_cast() {
std::cout
<< "==================================================================\n"
<< "= This device is expected to load x509 certs as a cast receiver. =\n"
@@ -38,6 +40,8 @@ int CheckAndInstallProv30ROT() {
return 0;
}
} // namespace
// This special main procedure is used instead of the standard GTest main,
// because we need to initialize the list of features supported by the device.
// Also, the test filter is updated based on the feature list.

View File

@@ -9,7 +9,9 @@
namespace wvoec {
namespace {
bool g_generate_corpus;
}
void AppendToFile(const std::string& file_name, const char* message,
const size_t message_size) {

View File

@@ -604,11 +604,13 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, ContinueDecryptionAfterIdleAndWake) {
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
}
namespace {
// Used to construct a specific pattern.
constexpr OEMCrypto_CENCEncryptPatternDesc MakePattern(size_t encrypt,
size_t skip) {
return {encrypt, skip};
}
} // namespace
INSTANTIATE_TEST_SUITE_P(
CTRTests, OEMCryptoSessionTestsDecryptTests,

View File

@@ -8,18 +8,6 @@ using namespace wvoec;
namespace wvoec {
// Make this function available when in Fuzz mode because we are not inheriting
// from OEMCryptoClientTest.
const uint8_t* find(const vector<uint8_t>& message,
const vector<uint8_t>& substring) {
vector<uint8_t>::const_iterator pos = search(
message.begin(), message.end(), substring.begin(), substring.end());
if (pos == message.end()) {
return nullptr;
}
return &(*pos);
}
void SessionUtil::CreateWrappedDRMKey() {
if (global_features.provisioning_method == OEMCrypto_BootCertificateChain) {
// Have the device create a wrapped key.