From 4d7025e5178def0acda55daa3dfeec3901af84c9 Mon Sep 17 00:00:00 2001 From: Vicky Min Date: Wed, 8 Nov 2023 13:42:54 -0800 Subject: [PATCH] ODK implementation for license release PiperOrigin-RevId: 580643396 Change-Id: I588ef20587acc347b510dfb7fd9e372d221100a0 --- .../odk/include/core_message_deserialize.h | 10 ++++++ .../odk/include/core_message_serialize.h | 17 ++++++++++ .../odk/include/core_message_types.h | 11 +++++++ libwvdrmengine/oemcrypto/odk/include/odk.h | 2 +- .../oemcrypto/odk/include/odk_structs.h | 12 ++++++- .../odk/src/core_message_deserialize.cpp | 9 ++++++ .../odk/src/core_message_serialize.cpp | 16 ++++++++++ libwvdrmengine/oemcrypto/odk/src/odk.c | 32 +++++++++++++++++++ .../oemcrypto/odk/src/odk_serialize.c | 19 +++++++++++ .../oemcrypto/odk/src/odk_serialize.h | 6 ++++ .../oemcrypto/odk/src/odk_structs_priv.h | 13 ++++++-- .../oemcrypto/odk/test/odk_test_helper.cpp | 8 +++++ .../oemcrypto/odk/test/odk_test_helper.h | 12 +++++++ 13 files changed, 163 insertions(+), 4 deletions(-) diff --git a/libwvdrmengine/oemcrypto/odk/include/core_message_deserialize.h b/libwvdrmengine/oemcrypto/odk/include/core_message_deserialize.h index ce4ba206..fb80dc5e 100644 --- a/libwvdrmengine/oemcrypto/odk/include/core_message_deserialize.h +++ b/libwvdrmengine/oemcrypto/odk/include/core_message_deserialize.h @@ -34,6 +34,16 @@ namespace deserialize { bool CoreLicenseRequestFromMessage(const std::string& oemcrypto_core_message, ODK_LicenseRequest* core_license_request); +/** + * Counterpart (deserializer) of ODK_PrepareCoreReleaseRequest (serializer) + * + * Parameters: + * [in] oemcrypto_core_message + * [out] core_license_request + */ +bool CoreReleaseRequestFromMessage(const std::string& oemcrypto_core_message, + ODK_ReleaseRequest* core_release_request); + /** * Counterpart (deserializer) of ODK_PrepareCoreRenewalRequest (serializer) * diff --git a/libwvdrmengine/oemcrypto/odk/include/core_message_serialize.h b/libwvdrmengine/oemcrypto/odk/include/core_message_serialize.h index cfbe8354..7e3bd258 100644 --- a/libwvdrmengine/oemcrypto/odk/include/core_message_serialize.h +++ b/libwvdrmengine/oemcrypto/odk/include/core_message_serialize.h @@ -44,6 +44,23 @@ bool CreateCoreLicenseResponse(const CoreMessageFeatures& features, const std::string& core_request_sha256, std::string* oemcrypto_core_message); +/** + * Counterpart (serializer) of ODK_ParseLicense (deserializer) + * struct-input variant + * + * Parameters: + * [in] features feature support for response message. + * [in] core_request + * [in] seconds_since_license_requested + * [in] seconds_since_first_decrypt + * [out] oemcrypto_core_message + */ +bool CreateCoreReleaseResponse(const CoreMessageFeatures& features, + const ODK_ReleaseRequest& core_request, + int64_t seconds_since_license_requested, + int64_t seconds_since_first_decrypt, + std::string* oemcrypto_core_message); + /** * Counterpart (serializer) of ODK_ParseRenewal (deserializer) * diff --git a/libwvdrmengine/oemcrypto/odk/include/core_message_types.h b/libwvdrmengine/oemcrypto/odk/include/core_message_types.h index 239ea1ba..05f66c13 100644 --- a/libwvdrmengine/oemcrypto/odk/include/core_message_types.h +++ b/libwvdrmengine/oemcrypto/odk/include/core_message_types.h @@ -101,6 +101,17 @@ struct ODK_LicenseRequest { ODK_MessageCounter counter_info; }; +/** + * Output structure for CoreReleaseRequestFromMessage + * Input structure for CreateCoreReleaseResponse + */ +struct ODK_ReleaseRequest { + uint16_t api_minor_version; + uint16_t api_major_version; + uint32_t nonce; + uint32_t session_id; +}; + /** * Output structure for CoreRenewalRequestFromMessage * Input structure for CreateCoreRenewalResponse diff --git a/libwvdrmengine/oemcrypto/odk/include/odk.h b/libwvdrmengine/oemcrypto/odk/include/odk.h index 407f45de..92cfc953 100644 --- a/libwvdrmengine/oemcrypto/odk/include/odk.h +++ b/libwvdrmengine/oemcrypto/odk/include/odk.h @@ -312,7 +312,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest( * @version * This method is new in version 19 of the API. */ -OEMCryptoResult ODK_PrepareCoreLicenseRelease( +OEMCryptoResult ODK_PrepareCoreReleaseRequest( uint8_t* message, size_t message_length, size_t* core_message_size, const ODK_NonceValues* nonce_values, const ODK_MessageCounterInfo* counter_info, uint32_t status, diff --git a/libwvdrmengine/oemcrypto/odk/include/odk_structs.h b/libwvdrmengine/oemcrypto/odk/include/odk_structs.h index 781ac478..e03ce9ce 100644 --- a/libwvdrmengine/oemcrypto/odk/include/odk_structs.h +++ b/libwvdrmengine/oemcrypto/odk/include/odk_structs.h @@ -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 v19.0 2023-11-07" +#define ODK_RELEASE_DATE "ODK v19.0 2023-11-08" /* The lowest version number for an ODK message. */ #define ODK_FIRST_VERSION 16 @@ -289,6 +289,16 @@ typedef struct { OEMCrypto_KeyObject* key_array; } ODK_Packing_ParsedLicense; +/** + * The parsed release structure does not currently contain information from or + * about the license message. This struct is a placeholder for future cases + * where data may need to be added to the parsed release. + * @version + * This struct is new in API version 19. + */ +typedef struct { +} ODK_ParsedRelease; + /** * The parsed provisioning structure contains information from the license * message. The function ODK_ParseProvisioning will fill in the fields of diff --git a/libwvdrmengine/oemcrypto/odk/src/core_message_deserialize.cpp b/libwvdrmengine/oemcrypto/odk/src/core_message_deserialize.cpp index 79ee2b6a..c9901014 100644 --- a/libwvdrmengine/oemcrypto/odk/src/core_message_deserialize.cpp +++ b/libwvdrmengine/oemcrypto/odk/src/core_message_deserialize.cpp @@ -11,6 +11,7 @@ #include #include "OEMCryptoCENCCommon.h" +#include "core_message_types.h" #include "odk_message.h" #include "odk_serialize.h" #include "odk_structs.h" @@ -147,6 +148,14 @@ bool CoreLicenseRequestFromMessage(const std::string& oemcrypto_core_message, return true; } +bool CoreReleaseRequestFromMessage(const std::string& oemcrypto_core_message, + ODK_ReleaseRequest* core_release_request) { + ODK_PreparedReleaseRequest prepared_release = {}; + return ParseRequest(ODK_Release_Request_Type, oemcrypto_core_message, + core_release_request, &prepared_release, + Unpack_ODK_PreparedReleaseRequest); +} + bool CoreRenewalRequestFromMessage(const std::string& oemcrypto_core_message, ODK_RenewalRequest* core_renewal_request) { const auto unpacker = Unpack_ODK_PreparedRenewalRequest; diff --git a/libwvdrmengine/oemcrypto/odk/src/core_message_serialize.cpp b/libwvdrmengine/oemcrypto/odk/src/core_message_serialize.cpp index e8c74076..b2fc97bf 100644 --- a/libwvdrmengine/oemcrypto/odk/src/core_message_serialize.cpp +++ b/libwvdrmengine/oemcrypto/odk/src/core_message_serialize.cpp @@ -10,6 +10,7 @@ #include #include +#include "core_message_types.h" #include "odk_serialize.h" #include "odk_structs.h" #include "odk_structs_priv.h" @@ -137,6 +138,21 @@ bool CreateCoreLicenseResponse(const CoreMessageFeatures& features, Pack_ODK_LicenseResponse); } +bool CreateCoreReleaseResponse(const CoreMessageFeatures& features, + const ODK_ReleaseRequest& core_request, + int64_t seconds_since_license_requested, + int64_t seconds_since_first_decrypt, + std::string* oemcrypto_core_message) { + ODK_ReleaseResponse release_response{}; + if (!CreateResponseHeader(features, ODK_Release_Response_Type, + &release_response.core_message, core_request)) { + return false; + } + return CreateResponse(ODK_Release_Response_Type, oemcrypto_core_message, + &release_response.core_message, release_response, + Pack_ODK_ReleaseResponse); +} + bool CreateCoreRenewalResponse(const CoreMessageFeatures& features, const ODK_RenewalRequest& core_request, uint64_t renewal_duration_seconds, diff --git a/libwvdrmengine/oemcrypto/odk/src/odk.c b/libwvdrmengine/oemcrypto/odk/src/odk.c index 2f063bac..dc52b0ab 100644 --- a/libwvdrmengine/oemcrypto/odk/src/odk.c +++ b/libwvdrmengine/oemcrypto/odk/src/odk.c @@ -66,6 +66,15 @@ static OEMCryptoResult ODK_PrepareRequest( } break; } + case ODK_Release_Request_Type: { + core_message->message_length = ODK_RELEASE_REQUEST_SIZE; + if (sizeof(ODK_PreparedReleaseRequest) > prepared_request_buffer_length) { + return ODK_ERROR_CORE_MESSAGE; + } + Pack_ODK_PreparedReleaseRequest( + &msg, (ODK_PreparedReleaseRequest*)prepared_request_buffer); + break; + } case ODK_Renewal_Request_Type: { core_message->message_length = ODK_RENEWAL_REQUEST_SIZE; if (sizeof(ODK_PreparedRenewalRequest) > prepared_request_buffer_length) { @@ -224,6 +233,29 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest( } } +OEMCryptoResult ODK_PrepareCoreReleaseRequest( + uint8_t* message, size_t message_length, size_t* core_message_size, + const ODK_NonceValues* nonce_values, + const ODK_MessageCounterInfo* counter_info, uint32_t status, + uint32_t clock_security_level, int64_t seconds_since_license_requested, + int64_t seconds_since_first_decrypt) { + if (core_message_size == NULL || nonce_values == NULL || + counter_info == NULL) { + return ODK_ERROR_CORE_MESSAGE; + } + if (nonce_values->api_major_version >= 19) { + ODK_PreparedReleaseRequest release_request = {0}; + return ODK_PrepareRequest( + message, message_length, core_message_size, ODK_Release_Request_Type, + nonce_values, &release_request, sizeof(ODK_PreparedReleaseRequest)); + } else { + // If the version is pre 19 when license release isn't supported, create a + // license request. + return ODK_PrepareCoreLicenseRequest( + message, message_length, core_message_size, nonce_values, counter_info); + } +} + OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message, size_t message_length, size_t* core_message_size, diff --git a/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c b/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c index 72dd360e..04982fa4 100644 --- a/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c +++ b/libwvdrmengine/oemcrypto/odk/src/odk_serialize.c @@ -124,6 +124,11 @@ void Pack_ODK_PreparedLicenseRequestV17( Pack_ODK_CoreMessage(msg, &obj->core_message); } +void Pack_ODK_PreparedReleaseRequest(ODK_Message* msg, + const ODK_PreparedReleaseRequest* obj) { + Pack_ODK_CoreMessage(msg, &obj->core_message); +} + void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg, ODK_PreparedRenewalRequest const* obj) { Pack_ODK_CoreMessage(msg, &obj->core_message); @@ -178,6 +183,11 @@ void Pack_ODK_LicenseResponse(ODK_Message* msg, } } +void Pack_ODK_ReleaseResponse(ODK_Message* msg, + ODK_ReleaseResponse const* obj) { + Pack_ODK_CoreMessage(msg, &obj->core_message); +} + void Pack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse const* obj) { Pack_ODK_PreparedRenewalRequest(msg, &obj->request); @@ -318,6 +328,11 @@ void Unpack_ODK_PreparedLicenseRequestV17(ODK_Message* msg, Unpack_ODK_CoreMessage(msg, &obj->core_message); } +void Unpack_ODK_PreparedReleaseRequest(ODK_Message* msg, + ODK_PreparedReleaseRequest* obj) { + Unpack_ODK_CoreMessage(msg, &obj->core_message); +} + void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg, ODK_PreparedRenewalRequest* obj) { Unpack_ODK_CoreMessage(msg, &obj->core_message); @@ -380,6 +395,10 @@ void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj) { } } +void Unpack_ODK_ReleaseResponse(ODK_Message* msg, ODK_ReleaseResponse* obj) { + Unpack_ODK_CoreMessage(msg, &obj->core_message); +} + void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj) { Unpack_ODK_PreparedRenewalRequest(msg, &obj->request); Unpack_uint64_t(msg, &obj->renewal_duration_seconds); diff --git a/libwvdrmengine/oemcrypto/odk/src/odk_serialize.h b/libwvdrmengine/oemcrypto/odk/src/odk_serialize.h index 11996590..a7aa2208 100644 --- a/libwvdrmengine/oemcrypto/odk/src/odk_serialize.h +++ b/libwvdrmengine/oemcrypto/odk/src/odk_serialize.h @@ -20,6 +20,8 @@ void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg, const ODK_PreparedLicenseRequest* obj); void Pack_ODK_PreparedLicenseRequestV17( ODK_Message* msg, const ODK_PreparedLicenseRequestV17* obj); +void Pack_ODK_PreparedReleaseRequest(ODK_Message* msg, + const ODK_PreparedReleaseRequest* obj); void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg, const ODK_PreparedRenewalRequest* obj); void Pack_ODK_PreparedProvisioningRequest( @@ -34,6 +36,7 @@ void Pack_ODK_PreparedRenewedProvisioningRequest( /* odk unpack */ void Unpack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage* obj); void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj); +void Unpack_ODK_ReleaseResponse(ODK_Message* msg, ODK_ReleaseResponse* obj); void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj); void Unpack_ODK_ProvisioningResponse(ODK_Message* msg, ODK_ProvisioningResponse* obj); @@ -45,6 +48,7 @@ void Unpack_ODK_Provisioning40Response(ODK_Message* msg, /* kdo pack */ void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_Packing_LicenseResponse* obj); +void Pack_ODK_ReleaseResponse(ODK_Message* msg, const ODK_ReleaseResponse* obj); void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj); void Pack_ODK_ProvisioningResponse(ODK_Message* msg, const ODK_ProvisioningResponse* obj); @@ -58,6 +62,8 @@ void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg, ODK_PreparedLicenseRequest* obj); void Unpack_ODK_PreparedLicenseRequestV17(ODK_Message* msg, ODK_PreparedLicenseRequestV17* obj); +void Unpack_ODK_PreparedReleaseRequest(ODK_Message* msg, + ODK_PreparedReleaseRequest* obj); void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg, ODK_PreparedRenewalRequest* obj); void Unpack_ODK_PreparedProvisioningRequest( diff --git a/libwvdrmengine/oemcrypto/odk/src/odk_structs_priv.h b/libwvdrmengine/oemcrypto/odk/src/odk_structs_priv.h index 43025c78..b9bd4657 100644 --- a/libwvdrmengine/oemcrypto/odk/src/odk_structs_priv.h +++ b/libwvdrmengine/oemcrypto/odk/src/odk_structs_priv.h @@ -24,13 +24,13 @@ typedef uint32_t ODK_MessageType; #define ODK_Renewal_Response_Type ((ODK_MessageType)4u) #define ODK_Provisioning_Request_Type ((ODK_MessageType)5u) #define ODK_Provisioning_Response_Type ((ODK_MessageType)6u) +#define ODK_Release_Request_Type ((ODK_MessageType)7u) +#define ODK_Release_Response_Type ((ODK_MessageType)8u) #define ODK_Renewed_Provisioning_Request_Type ((ODK_MessageType)11u) #define ODK_Provisioning40_Request_Type ((ODK_MessageType)12u) // TODO(b/244580447): Reserve future message types to support // forward compatibility. -#define ODK_Release_Request_Type ((ODK_MessageType)7u) -#define ODK_Release_Response_Type ((ODK_MessageType)8u) #define ODK_Common_Request_Type ((ODK_MessageType)9u) #define ODK_Common_Response_Type ((ODK_MessageType)10u) @@ -49,6 +49,10 @@ typedef struct { ODK_CoreMessage core_message; } ODK_PreparedLicenseRequestV17; +typedef struct { + ODK_CoreMessage core_message; +} ODK_PreparedReleaseRequest; + typedef struct { ODK_CoreMessage core_message; uint64_t playback_time; @@ -97,6 +101,10 @@ typedef struct { uint8_t request_hash[ODK_SHA256_HASH_SIZE]; } ODK_Packing_LicenseResponse; +typedef struct { + ODK_CoreMessage core_message; +} ODK_ReleaseResponse; + typedef struct { ODK_PreparedRenewalRequest request; uint64_t renewal_duration_seconds; @@ -124,6 +132,7 @@ typedef struct { #define ODK_CORE_MESSAGE_SIZE 20u #define ODK_LICENSE_REQUEST_SIZE 90u #define ODK_LICENSE_REQUEST_SIZE_V17 20u +#define ODK_RELEASE_REQUEST_SIZE 90u #define ODK_RENEWAL_REQUEST_SIZE 28u #define ODK_PROVISIONING_REQUEST_SIZE 94u #define ODK_PROVISIONING_REQUEST_SIZE_V17 88u diff --git a/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.cpp b/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.cpp index d585d61d..49b04824 100644 --- a/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.cpp +++ b/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.cpp @@ -266,6 +266,14 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params, } } +void ODK_SetDefaultReleaseResponseParams(ODK_ReleaseResponseParams* params) { + ODK_SetDefaultCoreFields(&(params->core_message), ODK_Release_Response_Type); + params->status = kActive; + params->clock_security_level = 0; + params->seconds_since_license_requested = 0; + params->seconds_since_first_decrypt = 0; +} + void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) { ODK_SetDefaultCoreFields(&(params->core_message), ODK_Renewal_Response_Type); params->system_time = 0xfaceb00c; diff --git a/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.h b/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.h index fef62789..ee292b1b 100644 --- a/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.h +++ b/libwvdrmengine/oemcrypto/odk/test/odk_test_helper.h @@ -58,6 +58,16 @@ struct ODK_LicenseResponseParams { std::vector extra_fields; }; +struct ODK_ReleaseResponseParams { + ODK_CoreMessage core_message; + uint32_t status; + uint32_t clock_security_level; + int64_t seconds_since_license_requested; + int64_t seconds_since_first_decrypt; + ODK_ParsedRelease parsed_release; + std::vector extra_fields; +}; + struct ODK_RenewalResponseParams { ODK_CoreMessage core_message; uint64_t system_time; @@ -89,6 +99,8 @@ void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message, ODK_MessageType message_type); void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params, uint32_t odk_major_version); +void ODK_SetDefaultReleaseResponseParams(ODK_ReleaseResponseParams* params, + uint32_t odk_major_version); void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params); void ODK_SetDefaultProvisioningResponseParams( ODK_ProvisioningResponseParams* params, uint32_t odk_major_version);