Update ODK to v17.1
This commit is contained in:
@@ -1,10 +1,22 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// Builds libwv_odk.a, The ODK Library (libwv_odk) is used by
|
// Builds libwv_odk.a, The ODK Library (libwv_odk) is used by
|
||||||
// the CDM and by oemcrypto implementations.
|
// the CDM and by oemcrypto implementations.
|
||||||
|
// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
|
||||||
|
// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
|
||||||
|
// DEPENDING ON IT IN YOUR PROJECT. ***
|
||||||
|
package {
|
||||||
|
// See: http://go/android-license-faq
|
||||||
|
// A large-scale-change added 'default_applicable_licenses' to import
|
||||||
|
// all of the 'license_kinds' from "vendor_widevine_license"
|
||||||
|
// to get the below license kinds:
|
||||||
|
// legacy_by_exception_only (by exception only)
|
||||||
|
default_applicable_licenses: ["vendor_widevine_license"],
|
||||||
|
}
|
||||||
|
|
||||||
cc_library_static {
|
cc_library_static {
|
||||||
name: "libwv_odk",
|
name: "libwv_odk",
|
||||||
include_dirs: [
|
include_dirs: [
|
||||||
@@ -15,6 +27,7 @@ cc_library_static {
|
|||||||
|
|
||||||
srcs: [
|
srcs: [
|
||||||
"src/odk.c",
|
"src/odk.c",
|
||||||
|
"src/odk_message.c",
|
||||||
"src/odk_overflow.c",
|
"src/odk_overflow.c",
|
||||||
"src/odk_serialize.c",
|
"src/odk_serialize.c",
|
||||||
"src/odk_timer.c",
|
"src/odk_timer.c",
|
||||||
@@ -39,6 +52,7 @@ cc_library_static {
|
|||||||
|
|
||||||
srcs: [
|
srcs: [
|
||||||
"src/core_message_deserialize.cpp",
|
"src/core_message_deserialize.cpp",
|
||||||
|
"src/core_message_features.cpp",
|
||||||
"src/core_message_serialize.cpp",
|
"src/core_message_serialize.cpp",
|
||||||
"src/core_message_serialize_proto.cpp",
|
"src/core_message_serialize_proto.cpp",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
@@ -61,7 +61,7 @@ typedef enum OEMCryptoResult {
|
|||||||
OEMCrypto_ERROR_INVALID_NONCE = 32,
|
OEMCrypto_ERROR_INVALID_NONCE = 32,
|
||||||
OEMCrypto_ERROR_TOO_MANY_KEYS = 33,
|
OEMCrypto_ERROR_TOO_MANY_KEYS = 33,
|
||||||
OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED = 34,
|
OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED = 34,
|
||||||
OEMCrypto_ERROR_INVALID_RSA_KEY = 35,
|
OEMCrypto_ERROR_INVALID_RSA_KEY = 35, /* deprecated */
|
||||||
OEMCrypto_ERROR_KEY_EXPIRED = 36,
|
OEMCrypto_ERROR_KEY_EXPIRED = 36,
|
||||||
OEMCrypto_ERROR_INSUFFICIENT_RESOURCES = 37,
|
OEMCrypto_ERROR_INSUFFICIENT_RESOURCES = 37,
|
||||||
OEMCrypto_ERROR_INSUFFICIENT_HDCP = 38,
|
OEMCrypto_ERROR_INSUFFICIENT_HDCP = 38,
|
||||||
@@ -88,6 +88,11 @@ typedef enum OEMCryptoResult {
|
|||||||
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
|
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
|
||||||
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
|
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
|
||||||
OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION = 60,
|
OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION = 60,
|
||||||
|
OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING = 61,
|
||||||
|
OEMCrypto_ERROR_UNSUPPORTED_CIPHER = 62,
|
||||||
|
OEMCrypto_ERROR_DVR_FORBIDDEN = 63,
|
||||||
|
OEMCrypto_ERROR_INSUFFICIENT_PRIVILEGE = 64,
|
||||||
|
OEMCrypto_ERROR_INVALID_KEY = 65,
|
||||||
/* ODK return values */
|
/* ODK return values */
|
||||||
ODK_ERROR_BASE = 1000,
|
ODK_ERROR_BASE = 1000,
|
||||||
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
|
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
|
||||||
@@ -96,6 +101,11 @@ typedef enum OEMCryptoResult {
|
|||||||
ODK_TIMER_EXPIRED = ODK_ERROR_BASE + 3,
|
ODK_TIMER_EXPIRED = ODK_ERROR_BASE + 3,
|
||||||
ODK_UNSUPPORTED_API = ODK_ERROR_BASE + 4,
|
ODK_UNSUPPORTED_API = ODK_ERROR_BASE + 4,
|
||||||
ODK_STALE_RENEWAL = ODK_ERROR_BASE + 5,
|
ODK_STALE_RENEWAL = ODK_ERROR_BASE + 5,
|
||||||
|
/* OPK return values */
|
||||||
|
OPK_ERROR_BASE = 2000,
|
||||||
|
OPK_ERROR_REMOTE_CALL = OPK_ERROR_BASE,
|
||||||
|
OPK_ERROR_INCOMPATIBLE_VERSION = OPK_ERROR_BASE + 1,
|
||||||
|
OPK_ERROR_NO_PERSISTENT_DATA = OPK_ERROR_BASE + 2,
|
||||||
} OEMCryptoResult;
|
} OEMCryptoResult;
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
@@ -110,6 +120,11 @@ typedef enum OEMCrypto_Usage_Entry_Status {
|
|||||||
kInactiveUnused = 4,
|
kInactiveUnused = 4,
|
||||||
} OEMCrypto_Usage_Entry_Status;
|
} OEMCrypto_Usage_Entry_Status;
|
||||||
|
|
||||||
|
typedef enum OEMCrypto_ProvisioningRenewalType {
|
||||||
|
OEMCrypto_NoRenewal = 0,
|
||||||
|
OEMCrypto_RenewalACert = 1,
|
||||||
|
} OEMCrypto_ProvisioningRenewalType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OEMCrypto_LicenseType is used in the license message to indicate if the key
|
* OEMCrypto_LicenseType is used in the license message to indicate if the key
|
||||||
* objects are for content keys, or for entitlement keys.
|
* objects are for content keys, or for entitlement keys.
|
||||||
@@ -117,7 +132,7 @@ typedef enum OEMCrypto_Usage_Entry_Status {
|
|||||||
typedef enum OEMCrypto_LicenseType {
|
typedef enum OEMCrypto_LicenseType {
|
||||||
OEMCrypto_ContentLicense = 0,
|
OEMCrypto_ContentLicense = 0,
|
||||||
OEMCrypto_EntitlementLicense = 1,
|
OEMCrypto_EntitlementLicense = 1,
|
||||||
OEMCrypto_LicenstType_MaxValue = OEMCrypto_EntitlementLicense,
|
OEMCrypto_LicenseType_MaxValue = OEMCrypto_EntitlementLicense,
|
||||||
} OEMCrypto_LicenseType;
|
} OEMCrypto_LicenseType;
|
||||||
|
|
||||||
/* Private key type used in the provisioning response. */
|
/* Private key type used in the provisioning response. */
|
||||||
@@ -136,6 +151,62 @@ typedef struct {
|
|||||||
size_t length;
|
size_t length;
|
||||||
} OEMCrypto_Substring;
|
} OEMCrypto_Substring;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to specify information about CMI Descriptor 0.
|
||||||
|
* @param id: ID value of CMI Descriptor assigned by DTLA.
|
||||||
|
* @param length: byte length of the usage rules field.
|
||||||
|
* @param data: usage rules data.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t id; // 0x00
|
||||||
|
uint8_t extension; // 0x00
|
||||||
|
uint16_t length; // 0x01
|
||||||
|
uint8_t data;
|
||||||
|
} OEMCrypto_DTCP2_CMI_Descriptor_0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to specify information about CMI Descriptor 1.
|
||||||
|
* @param id: ID value of CMI Descriptor assigned by DTLA.
|
||||||
|
* @param extension: specified by the CMI descriptor
|
||||||
|
* @param length: byte length of the usage rules field.
|
||||||
|
* @param data: usage rules data.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t id; // 0x01
|
||||||
|
uint8_t extension; // 0x00
|
||||||
|
uint16_t length; // 0x03
|
||||||
|
uint8_t data[3];
|
||||||
|
} OEMCrypto_DTCP2_CMI_Descriptor_1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to specify information about CMI Descriptor 2.
|
||||||
|
* @param id: ID value of CMI Descriptor assigned by DTLA.
|
||||||
|
* @param extension: specified by the CMI descriptor
|
||||||
|
* @param length: byte length of the usage rules field.
|
||||||
|
* @param data: usage rules data.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t id; // 0x02
|
||||||
|
uint8_t extension; // 0x00
|
||||||
|
uint16_t length; // 0x03
|
||||||
|
uint8_t data[3];
|
||||||
|
} OEMCrypto_DTCP2_CMI_Descriptor_2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to specify the required DTCP2 level. If dtcp2_required is 0, there are
|
||||||
|
* no requirements on any of the keys. If dtcp2_required is 1, any key with the
|
||||||
|
* kControlHDCPRequired bit set requires DTCP2 in its output.
|
||||||
|
* @param dtcp2_required: specifies whether dtcp2 is required. 0 = not required,
|
||||||
|
* 1 = DTCP2 required.
|
||||||
|
* @param cmi_descriptor_1: three bytes of CMI descriptor 1
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t dtcp2_required; // 0 = not required. 1 = DTCP2 v1 required.
|
||||||
|
OEMCrypto_DTCP2_CMI_Descriptor_0 cmi_descriptor_0;
|
||||||
|
OEMCrypto_DTCP2_CMI_Descriptor_1 cmi_descriptor_1;
|
||||||
|
OEMCrypto_DTCP2_CMI_Descriptor_2 cmi_descriptor_2;
|
||||||
|
} OEMCrypto_DTCP2_CMI_Packet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Points to the relevant fields for a content key. The fields are extracted
|
* Points to the relevant fields for a content key. The fields are extracted
|
||||||
* from the License Response message offered to OEMCrypto_LoadKeys(). Each
|
* from the License Response message offered to OEMCrypto_LoadKeys(). Each
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_DESERIALIZE_H_
|
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_DESERIALIZE_H_
|
||||||
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_DESERIALIZE_H_
|
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_DESERIALIZE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "core_message_types.h"
|
#include "core_message_types.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
@@ -53,6 +55,18 @@ bool CoreProvisioningRequestFromMessage(
|
|||||||
const std::string& oemcrypto_core_message,
|
const std::string& oemcrypto_core_message,
|
||||||
ODK_ProvisioningRequest* core_provisioning_request);
|
ODK_ProvisioningRequest* core_provisioning_request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counterpart (deserializer) of ODK_PrepareCoreRenewedProvisioningRequest
|
||||||
|
* (serializer)
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* [in] oemcrypto_core_message
|
||||||
|
* [out] core_provisioning_request
|
||||||
|
*/
|
||||||
|
bool CoreRenewedProvisioningRequestFromMessage(
|
||||||
|
const std::string& oemcrypto_core_message,
|
||||||
|
ODK_ProvisioningRequest* core_provisioning_request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializer counterpart is not used and is therefore not implemented.
|
* Serializer counterpart is not used and is therefore not implemented.
|
||||||
*
|
*
|
||||||
|
|||||||
44
oemcrypto/odk/include/core_message_features.h
Normal file
44
oemcrypto/odk/include/core_message_features.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2021 Google LLC. All rights reserved. This file and proprietary
|
||||||
|
// source code may only be used and distributed under the Widevine
|
||||||
|
// License Agreement.
|
||||||
|
|
||||||
|
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_FEATURES_H_
|
||||||
|
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_FEATURES_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace oemcrypto_core_message {
|
||||||
|
namespace features {
|
||||||
|
|
||||||
|
// Features that may be supported by core messages. By restricting values in
|
||||||
|
// this structure, we can turn off features at runtime. This is plain data, and
|
||||||
|
// is essentially a version number.
|
||||||
|
struct CoreMessageFeatures {
|
||||||
|
// A default set of features.
|
||||||
|
static const CoreMessageFeatures kDefaultFeatures;
|
||||||
|
|
||||||
|
// Create the default feature set for the given major version number.
|
||||||
|
static CoreMessageFeatures DefaultFeatures(uint32_t maximum_major_version);
|
||||||
|
|
||||||
|
// 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 16.5, the last version used by Chrome. This will
|
||||||
|
// change to 17.0 when v17 has been released.
|
||||||
|
uint32_t maximum_major_version = 17;
|
||||||
|
uint32_t maximum_minor_version = 0;
|
||||||
|
|
||||||
|
bool operator==(const CoreMessageFeatures &other) const;
|
||||||
|
bool operator!=(const CoreMessageFeatures &other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const CoreMessageFeatures &features);
|
||||||
|
|
||||||
|
} // namespace features
|
||||||
|
} // namespace oemcrypto_core_message
|
||||||
|
|
||||||
|
#endif // WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_FEATURES_H_
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
@@ -17,23 +17,29 @@
|
|||||||
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_
|
#ifndef WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_
|
||||||
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_
|
#define WIDEVINE_ODK_INCLUDE_CORE_MESSAGE_SERIALIZE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "core_message_features.h"
|
||||||
#include "core_message_types.h"
|
#include "core_message_types.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
namespace serialize {
|
namespace serialize {
|
||||||
|
using oemcrypto_core_message::features::CoreMessageFeatures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counterpart (serializer) of ODK_ParseLicense (deserializer)
|
* Counterpart (serializer) of ODK_ParseLicense (deserializer)
|
||||||
* struct-input variant
|
* struct-input variant
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
|
* [in] features feature support for response message.
|
||||||
* [in] parsed_lic
|
* [in] parsed_lic
|
||||||
* [in] core_request
|
* [in] core_request
|
||||||
* [in] core_request_sha256
|
* [in] core_request_sha256
|
||||||
* [out] oemcrypto_core_message
|
* [out] oemcrypto_core_message
|
||||||
*/
|
*/
|
||||||
bool CreateCoreLicenseResponse(const ODK_ParsedLicense& parsed_lic,
|
bool CreateCoreLicenseResponse(const CoreMessageFeatures& features,
|
||||||
|
const ODK_ParsedLicense& parsed_lic,
|
||||||
const ODK_LicenseRequest& core_request,
|
const ODK_LicenseRequest& core_request,
|
||||||
const std::string& core_request_sha256,
|
const std::string& core_request_sha256,
|
||||||
std::string* oemcrypto_core_message);
|
std::string* oemcrypto_core_message);
|
||||||
@@ -42,11 +48,13 @@ bool CreateCoreLicenseResponse(const ODK_ParsedLicense& parsed_lic,
|
|||||||
* Counterpart (serializer) of ODK_ParseRenewal (deserializer)
|
* Counterpart (serializer) of ODK_ParseRenewal (deserializer)
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
|
* [in] features feature support for response message.
|
||||||
* [in] core_request
|
* [in] core_request
|
||||||
* [in] renewal_duration_seconds
|
* [in] renewal_duration_seconds
|
||||||
* [out] oemcrypto_core_message
|
* [out] oemcrypto_core_message
|
||||||
*/
|
*/
|
||||||
bool CreateCoreRenewalResponse(const ODK_RenewalRequest& core_request,
|
bool CreateCoreRenewalResponse(const CoreMessageFeatures& features,
|
||||||
|
const ODK_RenewalRequest& core_request,
|
||||||
uint64_t renewal_duration_seconds,
|
uint64_t renewal_duration_seconds,
|
||||||
std::string* oemcrypto_core_message);
|
std::string* oemcrypto_core_message);
|
||||||
|
|
||||||
@@ -55,11 +63,13 @@ bool CreateCoreRenewalResponse(const ODK_RenewalRequest& core_request,
|
|||||||
* struct-input variant
|
* struct-input variant
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
|
* [in] features feature support for response message.
|
||||||
* [in] parsed_prov
|
* [in] parsed_prov
|
||||||
* [in] core_request
|
* [in] core_request
|
||||||
* [out] oemcrypto_core_message
|
* [out] oemcrypto_core_message
|
||||||
*/
|
*/
|
||||||
bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov,
|
bool CreateCoreProvisioningResponse(const CoreMessageFeatures& features,
|
||||||
|
const ODK_ParsedProvisioning& parsed_prov,
|
||||||
const ODK_ProvisioningRequest& core_request,
|
const ODK_ProvisioningRequest& core_request,
|
||||||
std::string* oemcrypto_core_message);
|
std::string* oemcrypto_core_message);
|
||||||
} // namespace serialize
|
} // namespace serialize
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
@@ -17,18 +17,19 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "core_message_features.h"
|
||||||
#include "core_message_types.h"
|
#include "core_message_types.h"
|
||||||
#include "license_protocol.pb.h"
|
#include "license_protocol.pb.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
namespace serialize {
|
namespace serialize {
|
||||||
|
|
||||||
// @ public create response (serializer) functions accepting proto input
|
// @ public create response (serializer) functions accepting proto input
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counterpart (serializer) of ODK_ParseLicense (deserializer)
|
* Counterpart (serializer) of ODK_ParseLicense (deserializer)
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
|
* [in] features feature support for response message.
|
||||||
* [in] serialized_license
|
* [in] serialized_license
|
||||||
serialized video_widevine::License
|
serialized video_widevine::License
|
||||||
* [in] core_request oemcrypto core message from request.
|
* [in] core_request oemcrypto core message from request.
|
||||||
@@ -37,23 +38,25 @@ namespace serialize {
|
|||||||
* [in] uses_padding - if the keys use padding.
|
* [in] uses_padding - if the keys use padding.
|
||||||
* [out] oemcrypto_core_message - the serialized oemcrypto core response.
|
* [out] oemcrypto_core_message - the serialized oemcrypto core response.
|
||||||
*/
|
*/
|
||||||
bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
bool CreateCoreLicenseResponseFromProto(
|
||||||
const ODK_LicenseRequest& core_request,
|
const oemcrypto_core_message::features::CoreMessageFeatures& features,
|
||||||
const std::string& core_request_sha256,
|
const std::string& serialized_license,
|
||||||
const bool nonce_required,
|
const ODK_LicenseRequest& core_request,
|
||||||
const bool uses_padding,
|
const std::string& core_request_sha256, const bool nonce_required,
|
||||||
std::string* oemcrypto_core_message);
|
const bool uses_padding, std::string* oemcrypto_core_message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counterpart (serializer) of ODK_ParseProvisioning (deserializer)
|
* Counterpart (serializer) of ODK_ParseProvisioning (deserializer)
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
|
* [in] features feature support for response message.
|
||||||
* [in] serialized_provisioning_response
|
* [in] serialized_provisioning_response
|
||||||
* serialized video_widevine::ProvisioningResponse
|
* serialized video_widevine::ProvisioningResponse
|
||||||
* [in] core_request
|
* [in] core_request
|
||||||
* [out] oemcrypto_core_message
|
* [out] oemcrypto_core_message
|
||||||
*/
|
*/
|
||||||
bool CreateCoreProvisioningResponseFromProto(
|
bool CreateCoreProvisioningResponseFromProto(
|
||||||
|
const oemcrypto_core_message::features::CoreMessageFeatures& features,
|
||||||
const std::string& serialized_provisioning_response,
|
const std::string& serialized_provisioning_response,
|
||||||
const ODK_ProvisioningRequest& core_request,
|
const ODK_ProvisioningRequest& core_request,
|
||||||
std::string* oemcrypto_core_message);
|
std::string* oemcrypto_core_message);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@@ -96,7 +96,8 @@ struct ODK_RenewalRequest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output structure for CoreProvisioningRequestFromMessage
|
* Output structure for CoreProvisioningRequestFromMessage and
|
||||||
|
* CoreRenewedProvisioningRequestFromMessage
|
||||||
* Input structure for CreateCoreProvisioningResponse
|
* Input structure for CreateCoreProvisioningResponse
|
||||||
*/
|
*/
|
||||||
struct ODK_ProvisioningRequest {
|
struct ODK_ProvisioningRequest {
|
||||||
@@ -105,6 +106,8 @@ struct ODK_ProvisioningRequest {
|
|||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
std::string device_id;
|
std::string device_id;
|
||||||
|
uint16_t renewal_type;
|
||||||
|
std::string renewal_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace oemcrypto_core_message
|
} // namespace oemcrypto_core_message
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,11 +132,11 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
|||||||
* This function sets the values in the clock_values structure. It shall be
|
* This function sets the values in the clock_values structure. It shall be
|
||||||
* called from OEMCrypto_LoadUsageEntry. When a usage entry from a v15 or
|
* called from OEMCrypto_LoadUsageEntry. When a usage entry from a v15 or
|
||||||
* earlier license is loaded, the value time_of_license_loaded shall be used
|
* earlier license is loaded, the value time_of_license_loaded shall be used
|
||||||
* in place of time_of_license_signed.
|
* in place of time_of_license_request_signed.
|
||||||
*
|
*
|
||||||
* @param[in,out] clock_values: the session's clock data.
|
* @param[in,out] clock_values: the session's clock data.
|
||||||
* @param[in] time_of_license_signed: the value time_license_received from the
|
* @param[in] time_of_license_request_signed: the value time_license_received
|
||||||
* loaded usage entry.
|
* from the loaded usage entry.
|
||||||
* @param[in] time_of_first_decrypt: the value time_of_first_decrypt from the
|
* @param[in] time_of_first_decrypt: the value time_of_first_decrypt from the
|
||||||
* loaded usage entry.
|
* loaded usage entry.
|
||||||
* @param[in] time_of_last_decrypt: the value time_of_last_decrypt from the
|
* @param[in] time_of_last_decrypt: the value time_of_last_decrypt from the
|
||||||
@@ -152,7 +152,7 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
|||||||
* This method is new in version 16 of the API.
|
* This method is new in version 16 of the API.
|
||||||
*/
|
*/
|
||||||
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
||||||
uint64_t time_of_license_signed,
|
uint64_t time_of_license_request_signed,
|
||||||
uint64_t time_of_first_decrypt,
|
uint64_t time_of_first_decrypt,
|
||||||
uint64_t time_of_last_decrypt,
|
uint64_t time_of_last_decrypt,
|
||||||
enum OEMCrypto_Usage_Entry_Status status,
|
enum OEMCrypto_Usage_Entry_Status status,
|
||||||
@@ -326,7 +326,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
|||||||
* OEMCrypto_GetDeviceID. The device ID shall be unique to the device, and
|
* OEMCrypto_GetDeviceID. The device ID shall be unique to the device, and
|
||||||
* stable across reboots and factory resets for an L1 device.
|
* stable across reboots and factory resets for an L1 device.
|
||||||
*
|
*
|
||||||
* NOTE: if the message pointer is null and/or input core_message_size is
|
* NOTE: if the message pointer is null and/or input core_message_length is
|
||||||
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||||
* core_message_size to the size needed.
|
* core_message_size to the size needed.
|
||||||
*
|
*
|
||||||
@@ -351,10 +351,56 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
|||||||
* This method is new in version 16 of the API.
|
* This method is new in version 16 of the API.
|
||||||
*/
|
*/
|
||||||
OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||||
uint8_t* message, size_t message_length, size_t* core_message_size,
|
uint8_t* message, size_t message_length, size_t* core_message_length,
|
||||||
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||||
size_t device_id_length);
|
size_t device_id_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the message to include a core renewal provisioning request at the
|
||||||
|
* beginning of the message buffer. The values in nonce_values are used to
|
||||||
|
* populate the message.
|
||||||
|
*
|
||||||
|
* This shall be called by OEMCrypto from
|
||||||
|
* OEMCrypto_PrepAndSignProvisioningRequest.
|
||||||
|
*
|
||||||
|
* The buffer device_id shall be the same string returned by
|
||||||
|
* OEMCrypto_GetDeviceID. The device ID shall be unique to the device, and
|
||||||
|
* stable across reboots and factory resets for an L1 device.
|
||||||
|
*
|
||||||
|
* NOTE: if the message pointer is null and/or input core_message_length is
|
||||||
|
* zero, this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||||
|
* core_message_size to the size needed.
|
||||||
|
*
|
||||||
|
* @param[in,out] message: pointer to memory for the entire message. Modified by
|
||||||
|
* the ODK library.
|
||||||
|
* @param[in] message_length: length of the entire message buffer.
|
||||||
|
* @param[in,out] core_message_size: length of the core message at the beginning
|
||||||
|
* of the message. (in) size of buffer reserved for the core message, in
|
||||||
|
* bytes. (out) actual length of the core message, in bytes.
|
||||||
|
* @param[in] nonce_values: pointer to the session's nonce data.
|
||||||
|
* @param[in] device_id: For devices with a keybox, this is the device ID from
|
||||||
|
* the keybox. For devices with an OEM Certificate, this is a device
|
||||||
|
* unique id string.
|
||||||
|
* @param[in] device_id_length: length of device_id. The device ID can be at
|
||||||
|
* most 64 bytes.
|
||||||
|
* @param[in] renewal_type: type of renewal used
|
||||||
|
* @param[in] renewal_data: renewal data used. For renewal_type = 1,
|
||||||
|
* renewal_data is the Android attestation batch certificate.
|
||||||
|
* @param[in] renewal_data_length: length of renewal_data
|
||||||
|
*
|
||||||
|
* @retval OEMCrypto_SUCCESS
|
||||||
|
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||||
|
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
|
||||||
|
*
|
||||||
|
* @version
|
||||||
|
* This method is new in version 17 of the API.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
uint8_t* message, size_t message_length, size_t* core_message_length,
|
||||||
|
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||||
|
size_t device_id_length, uint16_t renewal_type, const uint8_t* renewal_data,
|
||||||
|
size_t renewal_data_length);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// @addtogroup odk_timer
|
/// @addtogroup odk_timer
|
||||||
@@ -469,8 +515,6 @@ OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
|
|||||||
* and false when called for OEMCrypto_ReloadLicense.
|
* and false when called for OEMCrypto_ReloadLicense.
|
||||||
* @param[in] usage_entry_present: true if the session has a new usage entry
|
* @param[in] usage_entry_present: true if the session has a new usage entry
|
||||||
* associated with it created via OEMCrypto_CreateNewUsageEntry.
|
* associated with it created via OEMCrypto_CreateNewUsageEntry.
|
||||||
* @param[in] request_hash: the hash of the license request core message. This
|
|
||||||
* was computed by OEMCrypto when the license request was signed.
|
|
||||||
* @param[in,out] timer_limits: The session's timer limits. These will be
|
* @param[in,out] timer_limits: The session's timer limits. These will be
|
||||||
* updated.
|
* updated.
|
||||||
* @param[in,out] clock_values: The session's clock values. These will be
|
* @param[in,out] clock_values: The session's clock values. These will be
|
||||||
@@ -492,7 +536,6 @@ OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
|
|||||||
OEMCryptoResult ODK_ParseLicense(
|
OEMCryptoResult ODK_ParseLicense(
|
||||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
bool initial_license_load, bool usage_entry_present,
|
bool initial_license_load, bool usage_entry_present,
|
||||||
const uint8_t request_hash[ODK_SHA256_HASH_SIZE],
|
|
||||||
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
||||||
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license);
|
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license);
|
||||||
|
|
||||||
@@ -598,6 +641,20 @@ OEMCryptoResult ODK_ParseProvisioning(
|
|||||||
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||||
size_t device_id_length, ODK_ParsedProvisioning* parsed_response);
|
size_t device_id_length, ODK_ParsedProvisioning* parsed_response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function ODK_ParseProvisioning will parse the message and verify the
|
||||||
|
* API version is at most the version passed in.
|
||||||
|
*
|
||||||
|
* @param[in] nonce_values: pointer to the session's nonce data.
|
||||||
|
* @param[in] major_versioh: current API major version.
|
||||||
|
* @param[in] minor_version: current API minor version.
|
||||||
|
*
|
||||||
|
* @version
|
||||||
|
* This method is new in version 17 of the API.
|
||||||
|
*/
|
||||||
|
bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
|
||||||
|
uint16_t major_version, uint16_t minor_version);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_INCLUDE_ODK_ATTRIBUTES_H_
|
#ifndef WIDEVINE_ODK_INCLUDE_ODK_ATTRIBUTES_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
|
#ifndef WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
|
||||||
@@ -17,21 +17,21 @@ extern "C" {
|
|||||||
* ODK_Message is the structure that defines the serialized messages passed
|
* ODK_Message is the structure that defines the serialized messages passed
|
||||||
* between the REE and TEE. ODK_Message is an abstract data type that represents
|
* between the REE and TEE. ODK_Message is an abstract data type that represents
|
||||||
* the concept of a message without disclosing the implementation details. By
|
* the concept of a message without disclosing the implementation details. By
|
||||||
* hiding the internal structure, arbitrary modification to the message fields
|
* hiding the internal structure, modification of the message fields by code
|
||||||
* by code that is not privy to the message definition can be prevented. By
|
* that is not privy to the message definition can be prevented. If the message
|
||||||
* restricting message modification it is possible to enforce message validity
|
* definition was exposed, there could be serious yet subtle errors in message
|
||||||
* and integrity with a small set of primitives that can be careful reviewed.
|
* manipulation anywhere in the code base. By restricting message modification
|
||||||
* This is important because it allows the assertion to be made that a message's
|
* it is possible to enforce validity and integrity with a small set of
|
||||||
* fields are internally consistent after every operation. As an example, it
|
* primitives that can be carefully reviewed. Checks can be added to verify that
|
||||||
* can be guaranteed that the message status be checked prior to accessing any
|
* a message's fields are internally consistent before every operation. As an
|
||||||
* field, and that the status be set to the proper state when any parse error is
|
* example, it can be guaranteed that the message status will be checked prior
|
||||||
* detected. If the message definition was exposed, there could be fundamental
|
* to accessing any field so parsing will be stopped when the message status is
|
||||||
* yet subtle errors in message manipulation anywhere in the code base. It also
|
* set after any parse error is detected. This also makes development easier
|
||||||
* makes development easier since any access to the message structure can be
|
* since any access to the message structure can be tracked through a single
|
||||||
* tracked through a single point so, for example, it becomes possible to add
|
* point so, for example, it becomes possible to add trace statements globally
|
||||||
* trace statements globally to all message operations by only changing the
|
* to all message operations by only changing the field accessors. Finally it
|
||||||
* field accessors. Finally it simplies maintentance by localizing changes to
|
* simplifies maintenance by localizing changes to the message structure to a
|
||||||
* the message to a few files.
|
* few files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
@@ -48,17 +48,20 @@ typedef struct {
|
|||||||
} ALIGNED ODK_Message;
|
} ALIGNED ODK_Message;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MESSAGE_STATUS_OK = 0xe937fcf7,
|
MESSAGE_STATUS_OK = 0x7937fcf7,
|
||||||
MESSAGE_STATUS_UNKNOWN_ERROR = 0xe06c1190,
|
MESSAGE_STATUS_UNKNOWN_ERROR = 0x706c1190,
|
||||||
MESSAGE_STATUS_OVERFLOW_ERROR = 0xc43ae4bc,
|
MESSAGE_STATUS_OVERFLOW_ERROR = 0x543ae4bc,
|
||||||
MESSAGE_STATUS_UNDERFLOW_ERROR = 0x7123cd0b,
|
MESSAGE_STATUS_UNDERFLOW_ERROR = 0x7123cd0b,
|
||||||
MESSAGE_STATUS_PARSE_ERROR = 0x0b9f6189,
|
MESSAGE_STATUS_PARSE_ERROR = 0x0b9f6189,
|
||||||
MESSAGE_STATUS_NULL_POINTER_ERROR = 0x2d66837a,
|
MESSAGE_STATUS_NULL_POINTER_ERROR = 0x2d66837a,
|
||||||
MESSAGE_STATUS_API_VALUE_ERROR = 0x6ba34f47,
|
MESSAGE_STATUS_API_VALUE_ERROR = 0x6ba34f47,
|
||||||
MESSAGE_STATUS_END_OF_MESSAGE_ERROR = 0x998db72a,
|
MESSAGE_STATUS_END_OF_MESSAGE_ERROR = 0x798db72a,
|
||||||
MESSAGE_STATUS_INVALID_ENUM_VALUE = 0xedb88197,
|
MESSAGE_STATUS_INVALID_ENUM_VALUE = 0x7db88197,
|
||||||
MESSAGE_STATUS_INVALID_TAG_ERROR = 0x14dce06a,
|
MESSAGE_STATUS_INVALID_TAG_ERROR = 0x14dce06a,
|
||||||
MESSAGE_STATUS_NOT_INITIALIZED = 0x2990b6c6
|
MESSAGE_STATUS_NOT_INITIALIZED = 0x2990b6c6,
|
||||||
|
MESSAGE_STATUS_OUT_OF_MEMORY = 0x7c5c64cc,
|
||||||
|
MESSAGE_STATUS_MAP_SHARED_MEMORY_FAILED = 0x7afecacf,
|
||||||
|
MESSAGE_STATUS_SECURE_BUFFER_ERROR = 0x78f0e873
|
||||||
} ODK_MessageStatus;
|
} ODK_MessageStatus;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
#ifndef WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
||||||
#define WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
#define WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "odk_target.h"
|
#include "odk_target.h"
|
||||||
|
|
||||||
/* The version of this library. */
|
/* The version of this library. */
|
||||||
#define ODK_MAJOR_VERSION 16
|
#define ODK_MAJOR_VERSION 17
|
||||||
#define ODK_MINOR_VERSION 5
|
#define ODK_MINOR_VERSION 1
|
||||||
|
|
||||||
/* ODK Version string. Date changed automatically on each release. */
|
/* ODK Version string. Date changed automatically on each release. */
|
||||||
// TODO(b/163416999): Remove the following line when we upgrade to v17.
|
#define ODK_RELEASE_DATE "ODK v17.1 2022-06-17"
|
||||||
// The version 16.5 should not be used by any CE CDM release.
|
|
||||||
#define ODK_RELEASE_DATE "ODK v16.5 (ALCATRAZ ONLY) 2021-01-22"
|
|
||||||
// #define ODK_RELEASE_DATE "ODK v17.0 2021-01-22"
|
|
||||||
|
|
||||||
/* The lowest version number for an ODK message. */
|
/* The lowest version number for an ODK message. */
|
||||||
#define ODK_FIRST_VERSION 16
|
#define ODK_FIRST_VERSION 16
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
/* Some useful constants. */
|
/* Some useful constants. */
|
||||||
#define ODK_DEVICE_ID_LEN_MAX 64
|
#define ODK_DEVICE_ID_LEN_MAX 64
|
||||||
#define ODK_SHA256_HASH_SIZE 32
|
#define ODK_SHA256_HASH_SIZE 32
|
||||||
|
#define ODK_KEYBOX_RENEWAL_DATA_SIZE 1600
|
||||||
|
|
||||||
/// @addtogroup odk_timer
|
/// @addtogroup odk_timer
|
||||||
/// @{
|
/// @{
|
||||||
@@ -88,9 +90,9 @@ typedef struct {
|
|||||||
* on OEMCrypto's system clock, as described in the document "License
|
* on OEMCrypto's system clock, as described in the document "License
|
||||||
* Duration and Renewal".
|
* Duration and Renewal".
|
||||||
*
|
*
|
||||||
* @param time_of_license_signed: Time that the license request was signed,
|
* @param time_of_license_request_signed: Time that the license request was
|
||||||
* based on OEMCrypto's system clock. This value shall be stored and
|
* signed, based on OEMCrypto's system clock. This value shall be stored
|
||||||
* reloaded with usage entry as time_of_license_received.
|
* and reloaded with usage entry as time_of_license_received.
|
||||||
* @param time_of_first_decrypt: Time of the first decrypt or call select key,
|
* @param time_of_first_decrypt: Time of the first decrypt or call select key,
|
||||||
* based on OEMCrypto's system clock. This is 0 if the license has not
|
* based on OEMCrypto's system clock. This is 0 if the license has not
|
||||||
* been used to decrypt any data. This value shall be stored and reloaded
|
* been used to decrypt any data. This value shall be stored and reloaded
|
||||||
@@ -113,7 +115,7 @@ typedef struct {
|
|||||||
* This struct changed in API version 16.2.
|
* This struct changed in API version 16.2.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t time_of_license_signed;
|
uint64_t time_of_license_request_signed;
|
||||||
uint64_t time_of_first_decrypt;
|
uint64_t time_of_first_decrypt;
|
||||||
uint64_t time_of_last_decrypt;
|
uint64_t time_of_last_decrypt;
|
||||||
uint64_t time_of_renewal_request;
|
uint64_t time_of_renewal_request;
|
||||||
@@ -174,11 +176,13 @@ typedef struct {
|
|||||||
* entitlement keys.
|
* entitlement keys.
|
||||||
* @param nonce_required: indicates if the license requires a nonce.
|
* @param nonce_required: indicates if the license requires a nonce.
|
||||||
* @param timer_limits: time limits of the for the license.
|
* @param timer_limits: time limits of the for the license.
|
||||||
|
* @param watermarking: specifies if device supports watermarking.
|
||||||
|
* @param dtcp2_required: specifies if device supports DTCP.
|
||||||
* @param key_array_length: number of keys present.
|
* @param key_array_length: number of keys present.
|
||||||
* @param key_array: set of keys to be installed.
|
* @param key_array: set of keys to be installed.
|
||||||
*
|
*
|
||||||
* @version
|
* @version
|
||||||
* This struct changed in API version 16.2.
|
* This struct changed in API version 17.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
OEMCrypto_Substring enc_mac_keys_iv;
|
OEMCrypto_Substring enc_mac_keys_iv;
|
||||||
@@ -188,6 +192,8 @@ typedef struct {
|
|||||||
OEMCrypto_LicenseType license_type;
|
OEMCrypto_LicenseType license_type;
|
||||||
bool nonce_required;
|
bool nonce_required;
|
||||||
ODK_TimerLimits timer_limits;
|
ODK_TimerLimits timer_limits;
|
||||||
|
uint32_t watermarking;
|
||||||
|
OEMCrypto_DTCP2_CMI_Packet dtcp2_required;
|
||||||
uint32_t key_array_length;
|
uint32_t key_array_length;
|
||||||
OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
|
OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
|
||||||
} ODK_ParsedLicense;
|
} ODK_ParsedLicense;
|
||||||
@@ -215,4 +221,8 @@ typedef struct {
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
#endif // WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file is distributed
|
// Copyright 2019 Google LLC. All rights reserved. This file is distributed
|
||||||
// under the Widevine Master License Agreement.
|
// under the Widevine License Agreement.
|
||||||
|
|
||||||
// Partners are expected to edit this file to support target specific code
|
// Partners are expected to edit this file to support target specific code
|
||||||
// and limits.
|
// and limits.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "core_message_deserialize.h"
|
#include "core_message_deserialize.h"
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "odk_serialize.h"
|
#include "odk_serialize.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
#include "odk_structs_priv.h"
|
#include "odk_structs_priv.h"
|
||||||
@@ -52,6 +53,7 @@ bool ParseRequest(uint32_t message_type,
|
|||||||
core_request->api_minor_version = core_message.nonce_values.api_minor_version;
|
core_request->api_minor_version = core_message.nonce_values.api_minor_version;
|
||||||
core_request->nonce = core_message.nonce_values.nonce;
|
core_request->nonce = core_message.nonce_values.nonce;
|
||||||
core_request->session_id = core_message.nonce_values.session_id;
|
core_request->session_id = core_message.nonce_values.session_id;
|
||||||
|
|
||||||
// Verify that the minor version matches the released version for the given
|
// Verify that the minor version matches the released version for the given
|
||||||
// major version.
|
// major version.
|
||||||
if (core_request->api_major_version < ODK_FIRST_VERSION) {
|
if (core_request->api_major_version < ODK_FIRST_VERSION) {
|
||||||
@@ -68,10 +70,13 @@ bool ParseRequest(uint32_t message_type,
|
|||||||
// For v16, a release and a renewal use the same message structure.
|
// For v16, a release and a renewal use the same message structure.
|
||||||
// However, for future API versions, the release might be a separate
|
// However, for future API versions, the release might be a separate
|
||||||
// message. Otherwise, we expect an exact match of message types.
|
// message. Otherwise, we expect an exact match of message types.
|
||||||
|
// A provisioning request may contain a renewed provisioning message.
|
||||||
if (message_type != ODK_Common_Request_Type &&
|
if (message_type != ODK_Common_Request_Type &&
|
||||||
core_message.message_type != message_type &&
|
core_message.message_type != message_type &&
|
||||||
!(message_type == ODK_Renewal_Request_Type &&
|
!(message_type == ODK_Renewal_Request_Type &&
|
||||||
core_message.message_type == ODK_Release_Request_Type)) {
|
core_message.message_type == ODK_Release_Request_Type) &&
|
||||||
|
!(message_type == ODK_Provisioning_Request_Type &&
|
||||||
|
core_message.message_type == ODK_Renewed_Provisioning_Request_Type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Verify that the amount of buffer we read, which is GetOffset, is not more
|
// Verify that the amount of buffer we read, which is GetOffset, is not more
|
||||||
@@ -125,6 +130,42 @@ bool CoreProvisioningRequestFromMessage(
|
|||||||
}
|
}
|
||||||
core_provisioning_request->device_id.assign(
|
core_provisioning_request->device_id.assign(
|
||||||
reinterpret_cast<const char*>(device_id), device_id_length);
|
reinterpret_cast<const char*>(device_id), device_id_length);
|
||||||
|
core_provisioning_request->renewal_type = OEMCrypto_NoRenewal;
|
||||||
|
core_provisioning_request->renewal_data.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoreRenewedProvisioningRequestFromMessage(
|
||||||
|
const std::string& oemcrypto_core_message,
|
||||||
|
ODK_ProvisioningRequest* core_provisioning_request) {
|
||||||
|
const auto unpacker = Unpack_ODK_PreparedRenewedProvisioningRequest;
|
||||||
|
ODK_PreparedRenewedProvisioningRequest prepared_provision = {};
|
||||||
|
if (!ParseRequest(ODK_Renewed_Provisioning_Request_Type,
|
||||||
|
oemcrypto_core_message, core_provisioning_request,
|
||||||
|
&prepared_provision, unpacker)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uint8_t* device_id = prepared_provision.device_id;
|
||||||
|
const uint32_t device_id_length = prepared_provision.device_id_length;
|
||||||
|
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {};
|
||||||
|
if (memcmp(zero, device_id + device_id_length,
|
||||||
|
ODK_DEVICE_ID_LEN_MAX - device_id_length)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
core_provisioning_request->device_id.assign(
|
||||||
|
reinterpret_cast<const char*>(device_id), device_id_length);
|
||||||
|
|
||||||
|
if (prepared_provision.renewal_data_length >
|
||||||
|
sizeof(prepared_provision.renewal_data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
core_provisioning_request->renewal_type = OEMCrypto_RenewalACert;
|
||||||
|
core_provisioning_request->renewal_data.assign(
|
||||||
|
reinterpret_cast<const char*>(prepared_provision.renewal_data),
|
||||||
|
prepared_provision.renewal_data_length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
oemcrypto/odk/src/core_message_features.cpp
Normal file
41
oemcrypto/odk/src/core_message_features.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2021 Google LLC. All rights reserved. This file and proprietary
|
||||||
|
// source code may only be used and distributed under the Widevine
|
||||||
|
// License Agreement.
|
||||||
|
|
||||||
|
#include "core_message_features.h"
|
||||||
|
|
||||||
|
namespace oemcrypto_core_message {
|
||||||
|
namespace features {
|
||||||
|
const CoreMessageFeatures CoreMessageFeatures::kDefaultFeatures;
|
||||||
|
|
||||||
|
bool CoreMessageFeatures::operator==(const CoreMessageFeatures &other) const {
|
||||||
|
return maximum_major_version == other.maximum_major_version &&
|
||||||
|
maximum_minor_version == other.maximum_minor_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
switch (maximum_major_version) {
|
||||||
|
case 16:
|
||||||
|
features.maximum_minor_version = 5; // 16.5
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
features.maximum_minor_version = 1; // 17.1
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
features.maximum_minor_version = 0;
|
||||||
|
}
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os,
|
||||||
|
const CoreMessageFeatures &features) {
|
||||||
|
return os << "v" << features.maximum_major_version << "."
|
||||||
|
<< features.maximum_minor_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace features
|
||||||
|
} // namespace oemcrypto_core_message
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "core_message_serialize.h"
|
#include "core_message_serialize.h"
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "odk_serialize.h"
|
#include "odk_serialize.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
#include "odk_structs_priv.h"
|
#include "odk_structs_priv.h"
|
||||||
|
#include "odk_target.h"
|
||||||
#include "serialization_base.h"
|
#include "serialization_base.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
@@ -20,7 +21,45 @@ namespace serialize {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template for parsing requests
|
* Template for copying nonce values from request to response, and also
|
||||||
|
* computing the API version of the response.
|
||||||
|
*
|
||||||
|
* Template arguments:
|
||||||
|
* T: struct to be deserialized by odk
|
||||||
|
* S: kdo input struct
|
||||||
|
*/
|
||||||
|
template <typename T, typename S>
|
||||||
|
bool CreateResponseHeader(const CoreMessageFeatures& features,
|
||||||
|
ODK_MessageType message_type, const S& core_request,
|
||||||
|
T& response) {
|
||||||
|
// Bad major version.
|
||||||
|
if ((features.maximum_major_version > ODK_MAJOR_VERSION) ||
|
||||||
|
(features.maximum_major_version == ODK_MAJOR_VERSION &&
|
||||||
|
features.maximum_minor_version > ODK_MINOR_VERSION)) {
|
||||||
|
// TODO(b/147513335): this should be logged.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* header = &response.request.core_message;
|
||||||
|
header->message_type = message_type;
|
||||||
|
header->nonce_values.api_major_version = core_request.api_major_version;
|
||||||
|
header->nonce_values.api_minor_version = core_request.api_minor_version;
|
||||||
|
header->nonce_values.nonce = core_request.nonce;
|
||||||
|
header->nonce_values.session_id = core_request.session_id;
|
||||||
|
// The message API version for the response is the minimum of our version and
|
||||||
|
// the request's version.
|
||||||
|
if (core_request.api_major_version > features.maximum_major_version) {
|
||||||
|
header->nonce_values.api_major_version = features.maximum_major_version;
|
||||||
|
header->nonce_values.api_minor_version = features.maximum_minor_version;
|
||||||
|
} else if (core_request.api_major_version == features.maximum_major_version &&
|
||||||
|
core_request.api_minor_version > features.maximum_minor_version) {
|
||||||
|
header->nonce_values.api_minor_version = features.maximum_minor_version;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template for parsing requests and packing response
|
||||||
*
|
*
|
||||||
* Template arguments:
|
* Template arguments:
|
||||||
* T: struct to be deserialized by odk
|
* T: struct to be deserialized by odk
|
||||||
@@ -34,21 +73,11 @@ bool CreateResponse(ODK_MessageType message_type, const S& core_request,
|
|||||||
if (!oemcrypto_core_message) {
|
if (!oemcrypto_core_message) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* header = &response.request.core_message;
|
auto* header = &response.request.core_message;
|
||||||
header->message_type = message_type;
|
if (header->message_type != message_type ||
|
||||||
header->nonce_values.api_major_version = core_request.api_major_version;
|
header->nonce_values.api_major_version < ODK_FIRST_VERSION) {
|
||||||
header->nonce_values.api_minor_version = core_request.api_minor_version;
|
// This indicates CreateResponseHeader was not called.
|
||||||
header->nonce_values.nonce = core_request.nonce;
|
return false;
|
||||||
header->nonce_values.session_id = core_request.session_id;
|
|
||||||
// The message API version for the response is the minimum of our version and
|
|
||||||
// the request's version.
|
|
||||||
if (core_request.api_major_version > ODK_MAJOR_VERSION) {
|
|
||||||
header->nonce_values.api_major_version = ODK_MAJOR_VERSION;
|
|
||||||
header->nonce_values.api_minor_version = ODK_MINOR_VERSION;
|
|
||||||
} else if (core_request.api_major_version == ODK_MAJOR_VERSION &&
|
|
||||||
core_request.api_minor_version > ODK_MINOR_VERSION) {
|
|
||||||
header->nonce_values.api_minor_version = ODK_MINOR_VERSION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t BUF_CAPACITY = 2048;
|
static constexpr size_t BUF_CAPACITY = 2048;
|
||||||
@@ -59,7 +88,7 @@ bool CreateResponse(ODK_MessageType message_type, const S& core_request,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t message_length = ODK_Message_GetSize(&msg);
|
uint32_t message_length = static_cast<uint32_t>(ODK_Message_GetSize(&msg));
|
||||||
msg = ODK_Message_Create(buf.data() + sizeof(header->message_type),
|
msg = ODK_Message_Create(buf.data() + sizeof(header->message_type),
|
||||||
sizeof(header->message_length));
|
sizeof(header->message_length));
|
||||||
Pack_uint32_t(&msg, &message_length);
|
Pack_uint32_t(&msg, &message_length);
|
||||||
@@ -75,7 +104,7 @@ bool CopyDeviceId(const ODK_ProvisioningRequest& src,
|
|||||||
if (request.device_id_length > sizeof(request.device_id)) {
|
if (request.device_id_length > sizeof(request.device_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
request.device_id_length = device_id.size();
|
request.device_id_length = static_cast<uint32_t>(device_id.size());
|
||||||
memset(request.device_id, 0, sizeof(request.device_id));
|
memset(request.device_id, 0, sizeof(request.device_id));
|
||||||
memcpy(request.device_id, device_id.data(), request.device_id_length);
|
memcpy(request.device_id, device_id.data(), request.device_id_length);
|
||||||
return true;
|
return true;
|
||||||
@@ -83,33 +112,78 @@ bool CopyDeviceId(const ODK_ProvisioningRequest& src,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool CreateCoreLicenseResponse(const ODK_ParsedLicense& parsed_lic,
|
bool CreateCoreLicenseResponse(const CoreMessageFeatures& features,
|
||||||
|
const ODK_ParsedLicense& parsed_lic,
|
||||||
const ODK_LicenseRequest& core_request,
|
const ODK_LicenseRequest& core_request,
|
||||||
const std::string& core_request_sha256,
|
const std::string& core_request_sha256,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
ODK_LicenseResponse license_response{
|
ODK_LicenseResponse license_response{
|
||||||
{}, const_cast<ODK_ParsedLicense*>(&parsed_lic), {0}};
|
{}, const_cast<ODK_ParsedLicense*>(&parsed_lic)};
|
||||||
if (core_request_sha256.size() != sizeof(license_response.request_hash))
|
if (!CreateResponseHeader(features, ODK_License_Response_Type, core_request,
|
||||||
|
license_response)) {
|
||||||
return false;
|
return false;
|
||||||
memcpy(license_response.request_hash, core_request_sha256.data(),
|
}
|
||||||
sizeof(license_response.request_hash));
|
if (ODK_MAX_NUM_KEYS < license_response.parsed_license->key_array_length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (license_response.request.core_message.nonce_values.api_major_version ==
|
||||||
|
16) {
|
||||||
|
ODK_LicenseResponseV16 license_response_v16;
|
||||||
|
license_response_v16.request = license_response.request;
|
||||||
|
license_response_v16.parsed_license.enc_mac_keys_iv =
|
||||||
|
license_response.parsed_license->enc_mac_keys_iv;
|
||||||
|
license_response_v16.parsed_license.enc_mac_keys =
|
||||||
|
license_response.parsed_license->enc_mac_keys;
|
||||||
|
license_response_v16.parsed_license.pst =
|
||||||
|
license_response.parsed_license->pst;
|
||||||
|
license_response_v16.parsed_license.srm_restriction_data =
|
||||||
|
license_response.parsed_license->srm_restriction_data;
|
||||||
|
license_response_v16.parsed_license.license_type =
|
||||||
|
license_response.parsed_license->license_type;
|
||||||
|
license_response_v16.parsed_license.nonce_required =
|
||||||
|
license_response.parsed_license->nonce_required;
|
||||||
|
license_response_v16.parsed_license.timer_limits =
|
||||||
|
license_response.parsed_license->timer_limits;
|
||||||
|
license_response_v16.parsed_license.key_array_length =
|
||||||
|
license_response.parsed_license->key_array_length;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < license_response_v16.parsed_license.key_array_length &&
|
||||||
|
i < license_response.parsed_license->key_array_length;
|
||||||
|
i++) {
|
||||||
|
license_response_v16.parsed_license.key_array[i] =
|
||||||
|
license_response.parsed_license->key_array[i];
|
||||||
|
}
|
||||||
|
if (core_request_sha256.size() != sizeof(license_response_v16.request_hash))
|
||||||
|
return false;
|
||||||
|
memcpy(license_response_v16.request_hash, core_request_sha256.data(),
|
||||||
|
sizeof(license_response_v16.request_hash));
|
||||||
|
return CreateResponse(ODK_License_Response_Type, core_request,
|
||||||
|
oemcrypto_core_message, license_response_v16,
|
||||||
|
Pack_ODK_LicenseResponseV16);
|
||||||
|
}
|
||||||
return CreateResponse(ODK_License_Response_Type, core_request,
|
return CreateResponse(ODK_License_Response_Type, core_request,
|
||||||
oemcrypto_core_message, license_response,
|
oemcrypto_core_message, license_response,
|
||||||
Pack_ODK_LicenseResponse);
|
Pack_ODK_LicenseResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreateCoreRenewalResponse(const ODK_RenewalRequest& core_request,
|
bool CreateCoreRenewalResponse(const CoreMessageFeatures& features,
|
||||||
|
const ODK_RenewalRequest& core_request,
|
||||||
uint64_t renewal_duration_seconds,
|
uint64_t renewal_duration_seconds,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
ODK_RenewalResponse renewal_response{{}, core_request.playback_time_seconds};
|
ODK_RenewalResponse renewal_response{{}, core_request.playback_time_seconds};
|
||||||
renewal_response.request.playback_time = core_request.playback_time_seconds;
|
renewal_response.request.playback_time = core_request.playback_time_seconds;
|
||||||
renewal_response.renewal_duration_seconds = renewal_duration_seconds;
|
renewal_response.renewal_duration_seconds = renewal_duration_seconds;
|
||||||
|
if (!CreateResponseHeader(features, ODK_Renewal_Response_Type, core_request,
|
||||||
|
renewal_response)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return CreateResponse(ODK_Renewal_Response_Type, core_request,
|
return CreateResponse(ODK_Renewal_Response_Type, core_request,
|
||||||
oemcrypto_core_message, renewal_response,
|
oemcrypto_core_message, renewal_response,
|
||||||
Pack_ODK_RenewalResponse);
|
Pack_ODK_RenewalResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov,
|
bool CreateCoreProvisioningResponse(const CoreMessageFeatures& features,
|
||||||
|
const ODK_ParsedProvisioning& parsed_prov,
|
||||||
const ODK_ProvisioningRequest& core_request,
|
const ODK_ProvisioningRequest& core_request,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
ODK_ProvisioningResponse prov_response{
|
ODK_ProvisioningResponse prov_response{
|
||||||
@@ -117,6 +191,10 @@ bool CreateCoreProvisioningResponse(const ODK_ParsedProvisioning& parsed_prov,
|
|||||||
if (!CopyDeviceId(core_request, &prov_response)) {
|
if (!CopyDeviceId(core_request, &prov_response)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!CreateResponseHeader(features, ODK_Provisioning_Response_Type,
|
||||||
|
core_request, prov_response)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return CreateResponse(ODK_Provisioning_Response_Type, core_request,
|
return CreateResponse(ODK_Provisioning_Response_Type, core_request,
|
||||||
oemcrypto_core_message, prov_response,
|
oemcrypto_core_message, prov_response,
|
||||||
Pack_ODK_ProvisioningResponse);
|
Pack_ODK_ProvisioningResponse);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "core_message_serialize_proto.h"
|
#include "core_message_serialize_proto.h"
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
namespace serialize {
|
namespace serialize {
|
||||||
namespace {
|
namespace {
|
||||||
|
using oemcrypto_core_message::features::CoreMessageFeatures;
|
||||||
|
|
||||||
/* @ private functions */
|
/* @ private functions */
|
||||||
|
|
||||||
@@ -70,7 +71,8 @@ OEMCrypto_KeyObject KeyContainerToOecKey(
|
|||||||
|
|
||||||
// @ public create response functions
|
// @ public create response functions
|
||||||
|
|
||||||
bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
bool CreateCoreLicenseResponseFromProto(const CoreMessageFeatures& features,
|
||||||
|
const std::string& serialized_license,
|
||||||
const ODK_LicenseRequest& core_request,
|
const ODK_LicenseRequest& core_request,
|
||||||
const std::string& core_request_sha256,
|
const std::string& core_request_sha256,
|
||||||
const bool nonce_required,
|
const bool nonce_required,
|
||||||
@@ -99,8 +101,11 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
|||||||
}
|
}
|
||||||
case video_widevine::License_KeyContainer::CONTENT:
|
case video_widevine::License_KeyContainer::CONTENT:
|
||||||
case video_widevine::License_KeyContainer::OPERATOR_SESSION:
|
case video_widevine::License_KeyContainer::OPERATOR_SESSION:
|
||||||
|
case video_widevine::License_KeyContainer::OEM_CONTENT:
|
||||||
|
case video_widevine::License_KeyContainer::OEM_ENTITLEMENT:
|
||||||
case video_widevine::License_KeyContainer::ENTITLEMENT: {
|
case video_widevine::License_KeyContainer::ENTITLEMENT: {
|
||||||
if (k.type() == video_widevine::License_KeyContainer::ENTITLEMENT) {
|
if (k.type() == video_widevine::License_KeyContainer::ENTITLEMENT ||
|
||||||
|
k.type() == video_widevine::License_KeyContainer::OEM_ENTITLEMENT) {
|
||||||
any_entitlement = true;
|
any_entitlement = true;
|
||||||
} else {
|
} else {
|
||||||
any_content = true;
|
any_content = true;
|
||||||
@@ -133,12 +138,13 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
|||||||
parsed_lic.pst =
|
parsed_lic.pst =
|
||||||
GetOecSubstring(serialized_license, lid.provider_session_token());
|
GetOecSubstring(serialized_license, lid.provider_session_token());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lic.has_srm_requirement()) {
|
if (lic.has_srm_requirement()) {
|
||||||
parsed_lic.srm_restriction_data =
|
parsed_lic.srm_restriction_data =
|
||||||
GetOecSubstring(serialized_license, lic.srm_requirement());
|
GetOecSubstring(serialized_license, lic.srm_requirement());
|
||||||
}
|
}
|
||||||
|
if (lic.policy().has_watermarking_control()) {
|
||||||
|
parsed_lic.watermarking = lic.policy().watermarking_control();
|
||||||
|
}
|
||||||
parsed_lic.nonce_required = nonce_required;
|
parsed_lic.nonce_required = nonce_required;
|
||||||
const auto& policy = lic.policy();
|
const auto& policy = lic.policy();
|
||||||
ODK_TimerLimits& timer_limits = parsed_lic.timer_limits;
|
ODK_TimerLimits& timer_limits = parsed_lic.timer_limits;
|
||||||
@@ -154,11 +160,12 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
|||||||
policy.renewal_delay_seconds() +
|
policy.renewal_delay_seconds() +
|
||||||
policy.renewal_recovery_duration_seconds();
|
policy.renewal_recovery_duration_seconds();
|
||||||
|
|
||||||
return CreateCoreLicenseResponse(parsed_lic, core_request,
|
return CreateCoreLicenseResponse(features, parsed_lic, core_request,
|
||||||
core_request_sha256, oemcrypto_core_message);
|
core_request_sha256, oemcrypto_core_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreateCoreProvisioningResponseFromProto(
|
bool CreateCoreProvisioningResponseFromProto(
|
||||||
|
const CoreMessageFeatures& features,
|
||||||
const std::string& serialized_provisioning_resp,
|
const std::string& serialized_provisioning_resp,
|
||||||
const ODK_ProvisioningRequest& core_request,
|
const ODK_ProvisioningRequest& core_request,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
@@ -183,7 +190,7 @@ bool CreateCoreProvisioningResponseFromProto(
|
|||||||
GetOecSubstring(serialized_provisioning_resp, prov.wrapping_key());
|
GetOecSubstring(serialized_provisioning_resp, prov.wrapping_key());
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateCoreProvisioningResponse(parsed_prov, core_request,
|
return CreateCoreProvisioningResponse(features, parsed_prov, core_request,
|
||||||
oemcrypto_core_message);
|
oemcrypto_core_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
# source code may only be used and distributed under the Widevine Master License
|
# source code may only be used and distributed under the Widevine License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
# These files are used by the server and by some ODK test code. These files are
|
# These files are used by the server and by some ODK test code. These files are
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
'core_message_deserialize.cpp',
|
'core_message_deserialize.cpp',
|
||||||
|
'core_message_features.cpp',
|
||||||
'core_message_serialize.cpp',
|
'core_message_serialize.cpp',
|
||||||
'core_message_serialize_proto.cpp',
|
'core_message_serialize_proto.cpp',
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
@@ -72,6 +72,17 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ODK_Renewed_Provisioning_Request_Type: {
|
||||||
|
core_message->message_length = ODK_RENEWED_PROVISIONING_REQUEST_SIZE;
|
||||||
|
if (sizeof(ODK_PreparedRenewedProvisioningRequest) >
|
||||||
|
prepared_request_buffer_length) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
Pack_ODK_PreparedRenewedProvisioningRequest(
|
||||||
|
&msg,
|
||||||
|
(ODK_PreparedRenewedProvisioningRequest*)prepared_request_buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
@@ -91,64 +102,65 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static OEMCryptoResult ODK_ParseResponse(
|
/* Parse the core message and verify that it has the right type. The nonce
|
||||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
* values are updated to hold the response's API version.
|
||||||
ODK_MessageType message_type, const ODK_NonceValues* nonce_values,
|
*/
|
||||||
void* response_buffer, uint32_t response_buffer_length) {
|
static OEMCryptoResult ODK_ParseCoreHeader(const uint8_t* message,
|
||||||
if (message == NULL || response_buffer == NULL ||
|
size_t message_length,
|
||||||
core_message_length > message_length) {
|
size_t core_message_length,
|
||||||
|
ODK_MessageType message_type,
|
||||||
|
ODK_NonceValues* nonce_values) {
|
||||||
|
// The core_message_length is the length of the core message, which is a
|
||||||
|
// substring of the complete message.
|
||||||
|
if (message == NULL || core_message_length > message_length) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
ODK_CoreMessage core_message;
|
||||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||||
|
|
||||||
/* The core message should be at the beginning of the buffer, and with a
|
/* The core message should be at the beginning of the buffer. The core message
|
||||||
* shorter length. The core message is the part we are parsing. */
|
* is the part we are parsing. */
|
||||||
ODK_Message_SetSize(&msg, core_message_length);
|
ODK_Message_SetSize(&msg, core_message_length);
|
||||||
|
Unpack_ODK_CoreMessage(&msg, &core_message);
|
||||||
|
|
||||||
/* Parse message and unpack it into response buffer. */
|
|
||||||
switch (message_type) {
|
|
||||||
case ODK_License_Response_Type: {
|
|
||||||
if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
Unpack_ODK_LicenseResponse(&msg, (ODK_LicenseResponse*)response_buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ODK_Renewal_Response_Type: {
|
|
||||||
if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
Unpack_ODK_RenewalResponse(&msg, (ODK_RenewalResponse*)response_buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ODK_Provisioning_Response_Type: {
|
|
||||||
if (sizeof(ODK_ProvisioningResponse) > response_buffer_length) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
Unpack_ODK_ProvisioningResponse(
|
|
||||||
&msg, (ODK_ProvisioningResponse*)response_buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer;
|
|
||||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||||
message_type != core_message->message_type ||
|
message_type != core_message.message_type) {
|
||||||
ODK_Message_GetOffset(&msg) != core_message->message_length) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
// The current offset should be the end of the header, which is the message
|
||||||
|
// type, message length, api version, and nonce fields. The header can't be
|
||||||
|
// larger than the whole core message. Also, the core message specifies its
|
||||||
|
// length, which should be exactly the length of the core message buffer.
|
||||||
|
if (ODK_Message_GetOffset(&msg) > core_message.message_length ||
|
||||||
|
core_message.message_length != core_message_length) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
/* We do not support future API version. Also, this function should not be
|
||||||
|
* used for legacy licenses without a core message. */
|
||||||
|
if (core_message.nonce_values.api_major_version > ODK_MAJOR_VERSION ||
|
||||||
|
core_message.nonce_values.api_major_version < ODK_FIRST_VERSION) {
|
||||||
|
return ODK_UNSUPPORTED_API;
|
||||||
|
}
|
||||||
if (nonce_values) {
|
if (nonce_values) {
|
||||||
/* always verify nonce_values for Renewal and Provisioning responses */
|
/* If the server sent us an older format, record the message's API version.
|
||||||
if (!ODK_NonceValuesEqual(nonce_values, &(core_message->nonce_values))) {
|
*/
|
||||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
if (nonce_values->api_major_version >
|
||||||
|
core_message.nonce_values.api_major_version) {
|
||||||
|
// If the major version is smaller, use both values from the server.
|
||||||
|
nonce_values->api_major_version =
|
||||||
|
core_message.nonce_values.api_major_version;
|
||||||
|
nonce_values->api_minor_version =
|
||||||
|
core_message.nonce_values.api_minor_version;
|
||||||
|
} else if (nonce_values->api_major_version ==
|
||||||
|
core_message.nonce_values.api_major_version &&
|
||||||
|
nonce_values->api_minor_version >
|
||||||
|
core_message.nonce_values.api_minor_version) {
|
||||||
|
// Otherwise, if the major versions are equal, but the minor is smaller,
|
||||||
|
// then we should lower the minor version.
|
||||||
|
nonce_values->api_minor_version =
|
||||||
|
core_message.nonce_values.api_minor_version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,9 +174,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
|||||||
if (core_message_length == NULL || nonce_values == NULL) {
|
if (core_message_length == NULL || nonce_values == NULL) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
ODK_PreparedLicenseRequest license_request = {
|
ODK_PreparedLicenseRequest license_request = {0};
|
||||||
{0, 0, {}},
|
|
||||||
};
|
|
||||||
return ODK_PrepareRequest(
|
return ODK_PrepareRequest(
|
||||||
message, message_length, core_message_length, ODK_License_Request_Type,
|
message, message_length, core_message_length, ODK_License_Request_Type,
|
||||||
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
|
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
|
||||||
@@ -192,7 +202,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
|||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ODK_PreparedRenewalRequest renewal_request = {{0, 0, {}}, 0};
|
ODK_PreparedRenewalRequest renewal_request = {0};
|
||||||
/* First, we compute the time this request was made relative to the playback
|
/* First, we compute the time this request was made relative to the playback
|
||||||
* clock. */
|
* clock. */
|
||||||
if (clock_values->time_of_first_decrypt == 0) {
|
if (clock_values->time_of_first_decrypt == 0) {
|
||||||
@@ -225,11 +235,7 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
|||||||
if (core_message_length == NULL || nonce_values == NULL) {
|
if (core_message_length == NULL || nonce_values == NULL) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
ODK_PreparedProvisioningRequest provisioning_request = {
|
ODK_PreparedProvisioningRequest provisioning_request = {0};
|
||||||
{0, 0, {}},
|
|
||||||
0,
|
|
||||||
{0},
|
|
||||||
};
|
|
||||||
if (device_id_length > sizeof(provisioning_request.device_id)) {
|
if (device_id_length > sizeof(provisioning_request.device_id)) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
@@ -243,52 +249,124 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
|||||||
sizeof(ODK_PreparedProvisioningRequest));
|
sizeof(ODK_PreparedProvisioningRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
uint8_t* message, size_t message_length, size_t* core_message_length,
|
||||||
|
const ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||||
|
size_t device_id_length, uint16_t renewal_type, const uint8_t* renewal_data,
|
||||||
|
size_t renewal_data_length) {
|
||||||
|
if (core_message_length == NULL || nonce_values == NULL) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
ODK_PreparedRenewedProvisioningRequest provisioning_request = {0};
|
||||||
|
if (device_id_length > sizeof(provisioning_request.device_id)) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
provisioning_request.device_id_length = (uint32_t)device_id_length;
|
||||||
|
if (device_id) {
|
||||||
|
memcpy(provisioning_request.device_id, device_id, device_id_length);
|
||||||
|
}
|
||||||
|
if (renewal_data_length > sizeof(provisioning_request.renewal_data)) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
provisioning_request.renewal_type = renewal_type;
|
||||||
|
provisioning_request.renewal_data_length = (uint32_t)renewal_data_length;
|
||||||
|
if (renewal_data) {
|
||||||
|
memcpy(provisioning_request.renewal_data, renewal_data,
|
||||||
|
renewal_data_length);
|
||||||
|
}
|
||||||
|
return ODK_PrepareRequest(message, message_length, core_message_length,
|
||||||
|
ODK_Renewed_Provisioning_Request_Type, nonce_values,
|
||||||
|
&provisioning_request,
|
||||||
|
sizeof(provisioning_request));
|
||||||
|
}
|
||||||
|
|
||||||
/* @@ parse response functions */
|
/* @@ parse response functions */
|
||||||
|
|
||||||
OEMCryptoResult ODK_ParseLicense(
|
OEMCryptoResult ODK_ParseLicense(
|
||||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||||
bool initial_license_load, bool usage_entry_present,
|
bool initial_license_load, bool usage_entry_present,
|
||||||
const uint8_t* request_hash, ODK_TimerLimits* timer_limits,
|
ODK_TimerLimits* timer_limits, ODK_ClockValues* clock_values,
|
||||||
ODK_ClockValues* clock_values, ODK_NonceValues* nonce_values,
|
ODK_NonceValues* nonce_values, ODK_ParsedLicense* parsed_license) {
|
||||||
ODK_ParsedLicense* parsed_license) {
|
if (message == NULL || timer_limits == NULL || clock_values == NULL ||
|
||||||
if (message == NULL || request_hash == NULL || timer_limits == NULL ||
|
nonce_values == NULL || parsed_license == NULL) {
|
||||||
clock_values == NULL || nonce_values == NULL || parsed_license == NULL) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ODK_LicenseResponse license_response = {{{0, 0, {}}}, NULL, {0}};
|
const OEMCryptoResult err =
|
||||||
license_response.parsed_license = parsed_license;
|
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||||
|
ODK_License_Response_Type, nonce_values);
|
||||||
const OEMCryptoResult err = ODK_ParseResponse(
|
|
||||||
message, message_length, core_message_length, ODK_License_Response_Type,
|
|
||||||
NULL, &license_response, sizeof(ODK_LicenseResponse));
|
|
||||||
|
|
||||||
if (err != OEMCrypto_SUCCESS) {
|
if (err != OEMCrypto_SUCCESS) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We do not support future API version. Also, this function should not be
|
ODK_LicenseResponse license_response = {0};
|
||||||
* used for legacy licenses. */
|
license_response.parsed_license = parsed_license;
|
||||||
if (license_response.request.core_message.nonce_values.api_major_version >
|
|
||||||
ODK_MAJOR_VERSION ||
|
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||||
license_response.request.core_message.nonce_values.api_major_version <
|
ODK_Message_SetSize(&msg, core_message_length);
|
||||||
ODK_FIRST_VERSION) {
|
if (nonce_values->api_major_version == 16) {
|
||||||
return ODK_UNSUPPORTED_API;
|
ODK_LicenseResponseV16 license_response_v16 = {0};
|
||||||
|
Unpack_ODK_LicenseResponseV16(&msg, &license_response_v16);
|
||||||
|
|
||||||
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||||
|
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to manually set parsed_license fields to
|
||||||
|
// license_response_v16.parsed_license field values since
|
||||||
|
// license_response_v16 is no longer a pointer so parsed_license doesn't get
|
||||||
|
// updated during the unpacking.
|
||||||
|
parsed_license->enc_mac_keys_iv =
|
||||||
|
license_response_v16.parsed_license.enc_mac_keys_iv;
|
||||||
|
parsed_license->enc_mac_keys =
|
||||||
|
license_response_v16.parsed_license.enc_mac_keys;
|
||||||
|
parsed_license->pst = license_response_v16.parsed_license.pst;
|
||||||
|
parsed_license->srm_restriction_data =
|
||||||
|
license_response_v16.parsed_license.srm_restriction_data;
|
||||||
|
parsed_license->license_type =
|
||||||
|
license_response_v16.parsed_license.license_type;
|
||||||
|
parsed_license->nonce_required =
|
||||||
|
license_response_v16.parsed_license.nonce_required;
|
||||||
|
parsed_license->timer_limits =
|
||||||
|
license_response_v16.parsed_license.timer_limits;
|
||||||
|
parsed_license->key_array_length =
|
||||||
|
license_response_v16.parsed_license.key_array_length;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < parsed_license->key_array_length; i++) {
|
||||||
|
parsed_license->key_array[i] =
|
||||||
|
license_response_v16.parsed_license.key_array[i];
|
||||||
|
}
|
||||||
|
// Set fields not used in V16 to default values.
|
||||||
|
parsed_license->watermarking = 0;
|
||||||
|
// Set fields not used in V16 to default values.
|
||||||
|
parsed_license->dtcp2_required.dtcp2_required = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_0.id = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_0.extension = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_0.length = 1;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_0.data = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_1.id = 1;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_1.extension = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_1.length = 3;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_1.data[0] = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_1.data[1] = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_1.data[2] = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_2.id = 2;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_2.extension = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_2.length = 3;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_2.data[0] = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_2.data[1] = 0;
|
||||||
|
parsed_license->dtcp2_required.cmi_descriptor_2.data[2] = 0;
|
||||||
|
license_response.request = license_response_v16.request;
|
||||||
|
} else {
|
||||||
|
Unpack_ODK_LicenseResponse(&msg, &license_response);
|
||||||
|
|
||||||
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||||
|
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the server sent us an older format, record the license's API version. */
|
|
||||||
if (nonce_values->api_major_version >
|
|
||||||
license_response.request.core_message.nonce_values.api_major_version) {
|
|
||||||
nonce_values->api_major_version =
|
|
||||||
license_response.request.core_message.nonce_values.api_major_version;
|
|
||||||
nonce_values->api_minor_version =
|
|
||||||
license_response.request.core_message.nonce_values.api_minor_version;
|
|
||||||
} else if (nonce_values->api_minor_version >
|
|
||||||
license_response.request.core_message.nonce_values
|
|
||||||
.api_minor_version) {
|
|
||||||
nonce_values->api_minor_version =
|
|
||||||
license_response.request.core_message.nonce_values.api_minor_version;
|
|
||||||
}
|
|
||||||
/* If the license has a provider session token (pst), then OEMCrypto should
|
/* If the license has a provider session token (pst), then OEMCrypto should
|
||||||
* have a usage entry loaded. The opposite is also an error. */
|
* have a usage entry loaded. The opposite is also an error. */
|
||||||
if ((usage_entry_present && parsed_license->pst.length == 0) ||
|
if ((usage_entry_present && parsed_license->pst.length == 0) ||
|
||||||
@@ -315,15 +393,6 @@ OEMCryptoResult ODK_ParseLicense(
|
|||||||
nonce_values->session_id =
|
nonce_values->session_id =
|
||||||
license_response.request.core_message.nonce_values.session_id;
|
license_response.request.core_message.nonce_values.session_id;
|
||||||
}
|
}
|
||||||
/* For v16, in order to be backwards compatible with a v15 license server,
|
|
||||||
* OEMCrypto stores a hash of the core license request and only signs the
|
|
||||||
* message body. Here, when we process the license response, we verify that
|
|
||||||
* the server has the same hash of the core request. */
|
|
||||||
if (initial_license_load && parsed_license->nonce_required &&
|
|
||||||
crypto_memcmp(request_hash, license_response.request_hash,
|
|
||||||
ODK_SHA256_HASH_SIZE)) {
|
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
|
||||||
}
|
|
||||||
*timer_limits = parsed_license->timer_limits;
|
*timer_limits = parsed_license->timer_limits;
|
||||||
/* And update the clock values state. */
|
/* And update the clock values state. */
|
||||||
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
|
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
|
||||||
@@ -342,17 +411,27 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ODK_RenewalResponse renewal_response = {
|
const OEMCryptoResult err =
|
||||||
{{0, 0, {}}, 0},
|
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||||
0,
|
ODK_Renewal_Response_Type, NULL);
|
||||||
};
|
|
||||||
const OEMCryptoResult err = ODK_ParseResponse(
|
|
||||||
message, message_length, core_message_length, ODK_Renewal_Response_Type,
|
|
||||||
nonce_values, &renewal_response, sizeof(ODK_RenewalResponse));
|
|
||||||
|
|
||||||
if (err != OEMCrypto_SUCCESS) {
|
if (err != OEMCrypto_SUCCESS) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
ODK_RenewalResponse renewal_response = {0};
|
||||||
|
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||||
|
ODK_Message_SetSize(&msg, core_message_length);
|
||||||
|
Unpack_ODK_RenewalResponse(&msg, &renewal_response);
|
||||||
|
|
||||||
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||||
|
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||||
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
|
}
|
||||||
|
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||||
|
if (!ODK_NonceValuesEqualExcludingVersion(
|
||||||
|
nonce_values,
|
||||||
|
&(renewal_response.request.core_message.nonce_values))) {
|
||||||
|
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reference:
|
/* Reference:
|
||||||
* Doc: License Duration and Renewal (Changes for OEMCrypto v16)
|
* Doc: License Duration and Renewal (Changes for OEMCrypto v16)
|
||||||
@@ -381,21 +460,31 @@ OEMCryptoResult ODK_ParseProvisioning(
|
|||||||
parsed_response == NULL) {
|
parsed_response == NULL) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
const OEMCryptoResult err =
|
||||||
ODK_ProvisioningResponse provisioning_response = {{{0, 0, {}}, 0, {0}}, NULL};
|
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||||
|
ODK_Provisioning_Response_Type, NULL);
|
||||||
|
if (err != OEMCrypto_SUCCESS) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
ODK_ProvisioningResponse provisioning_response = {0};
|
||||||
provisioning_response.parsed_provisioning = parsed_response;
|
provisioning_response.parsed_provisioning = parsed_response;
|
||||||
|
|
||||||
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OEMCryptoResult err = ODK_ParseResponse(
|
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||||
message, message_length, core_message_length,
|
ODK_Message_SetSize(&msg, core_message_length);
|
||||||
ODK_Provisioning_Response_Type, nonce_values, &provisioning_response,
|
Unpack_ODK_ProvisioningResponse(&msg, &provisioning_response);
|
||||||
sizeof(ODK_ProvisioningResponse));
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||||
|
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||||
if (err != OEMCrypto_SUCCESS) {
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
return err;
|
}
|
||||||
|
/* always verify nonce_values for Renewal and Provisioning responses */
|
||||||
|
if (!ODK_NonceValuesEqualExcludingVersion(
|
||||||
|
nonce_values,
|
||||||
|
&(provisioning_response.request.core_message.nonce_values))) {
|
||||||
|
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crypto_memcmp(device_id, provisioning_response.request.device_id,
|
if (crypto_memcmp(device_id, provisioning_response.request.device_id,
|
||||||
@@ -413,3 +502,10 @@ OEMCryptoResult ODK_ParseProvisioning(
|
|||||||
|
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
|
||||||
|
uint16_t major_version, uint16_t minor_version) {
|
||||||
|
return nonce_values->api_major_version < major_version ||
|
||||||
|
(nonce_values->api_major_version == major_version &&
|
||||||
|
nonce_values->api_minor_version <= minor_version);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
# source code may only be used and distributed under the Widevine Master License
|
# source code may only be used and distributed under the Widevine License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
{
|
{
|
||||||
'targets': [
|
'targets': [
|
||||||
{
|
{
|
||||||
|
'toolsets' : [ 'target' ],
|
||||||
'target_name': 'odk',
|
'target_name': 'odk',
|
||||||
'type': 'static_library',
|
'type': 'static_library',
|
||||||
|
'standalone_static_library' : 1,
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'../include',
|
'../include',
|
||||||
'../../include',
|
'../../include',
|
||||||
@@ -14,9 +16,23 @@
|
|||||||
'includes' : [
|
'includes' : [
|
||||||
'odk.gypi',
|
'odk.gypi',
|
||||||
],
|
],
|
||||||
|
'cflags': [
|
||||||
|
# TODO(b/172518513): Remove this
|
||||||
|
'-Wno-error=cast-qual',
|
||||||
|
],
|
||||||
|
'defines': [
|
||||||
|
# Needed for <endian.h> to work.
|
||||||
|
'_DEFAULT_SOURCE',
|
||||||
|
],
|
||||||
'direct_dependent_settings': {
|
'direct_dependent_settings': {
|
||||||
|
'defines': [
|
||||||
|
# Needed for <endian.h> to work.
|
||||||
|
'_DEFAULT_SOURCE',
|
||||||
|
],
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
|
'.',
|
||||||
'../include',
|
'../include',
|
||||||
|
'../../include',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
# source code may only be used and distributed under the Widevine Master License
|
# source code may only be used and distributed under the Widevine License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
# These files are built into the ODK library on the device. They are also used
|
# These files are built into the ODK library on the device. They are also used
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_ODK_ASSERT_H_
|
#ifndef WIDEVINE_ODK_SRC_ODK_ASSERT_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
|
#ifndef WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
|
||||||
@@ -11,11 +11,23 @@ extern "C" {
|
|||||||
|
|
||||||
#if defined(__linux__) || defined(__ANDROID__)
|
#if defined(__linux__) || defined(__ANDROID__)
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
#define oemcrypto_htobe16 htobe16
|
||||||
|
#define oemcrypto_be16toh be16toh
|
||||||
#define oemcrypto_htobe32 htobe32
|
#define oemcrypto_htobe32 htobe32
|
||||||
#define oemcrypto_be32toh be32toh
|
#define oemcrypto_be32toh be32toh
|
||||||
#define oemcrypto_htobe64 htobe64
|
#define oemcrypto_htobe64 htobe64
|
||||||
#define oemcrypto_be64toh be64toh
|
#define oemcrypto_be64toh be64toh
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <libkern/OSByteOrder.h>
|
||||||
|
#define oemcrypto_htobe16 OSSwapHostToBigInt16
|
||||||
|
#define oemcrypto_be16toh OSSwapBigToHostInt16
|
||||||
|
#define oemcrypto_htobe32 OSSwapHostToBigInt32
|
||||||
|
#define oemcrypto_be32toh OSSwapBigToHostInt32
|
||||||
|
#define oemcrypto_htobe64 OSSwapHostToBigInt64
|
||||||
|
#define oemcrypto_be64toh OSSwapBigToHostInt64
|
||||||
#else /* defined(__linux__) || defined(__ANDROID__) */
|
#else /* defined(__linux__) || defined(__ANDROID__) */
|
||||||
|
uint32_t oemcrypto_htobe16(uint16_t u16);
|
||||||
|
uint32_t oemcrypto_be16toh(uint16_t u16);
|
||||||
uint32_t oemcrypto_htobe32(uint32_t u32);
|
uint32_t oemcrypto_htobe32(uint32_t u32);
|
||||||
uint32_t oemcrypto_be32toh(uint32_t u32);
|
uint32_t oemcrypto_be32toh(uint32_t u32);
|
||||||
uint64_t oemcrypto_htobe64(uint64_t u64);
|
uint64_t oemcrypto_htobe64(uint64_t u64);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "odk_message.h"
|
#include "odk_message.h"
|
||||||
@@ -26,9 +26,12 @@ static_assert(
|
|||||||
/*
|
/*
|
||||||
* Create a message structure that references a separate data buffer. An
|
* Create a message structure that references a separate data buffer. An
|
||||||
* initialized message is returned. The caller is responsible for ensuring that
|
* initialized message is returned. The caller is responsible for ensuring that
|
||||||
* the buffer remains allocated for the lifetime of the message. If |buffer|
|
* the buffer remains allocated for the lifetime of the message. |buffer| may be
|
||||||
* is NULL or |capacity| is zero, the message is invalid and the status
|
* NULL. Serialization into a message with a NULL buffer will cause the message
|
||||||
* will be set to MESSAGE_STATUS_NOT_INITIALIZED.
|
* size to be incremented, but no data will be written into the message
|
||||||
|
* buffer. This is useful for calculating the amount of space a message will
|
||||||
|
* need, prior to doing the actual serialization. The buffer contents are
|
||||||
|
* unchanged by this function.
|
||||||
*/
|
*/
|
||||||
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity) {
|
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity) {
|
||||||
assert(sizeof(ODK_Message) >= sizeof(ODK_Message_Impl));
|
assert(sizeof(ODK_Message) >= sizeof(ODK_Message_Impl));
|
||||||
@@ -36,25 +39,28 @@ ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity) {
|
|||||||
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)&message;
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)&message;
|
||||||
message_impl->base = buffer;
|
message_impl->base = buffer;
|
||||||
message_impl->capacity = capacity;
|
message_impl->capacity = capacity;
|
||||||
ODK_Message_Clear(&message);
|
message_impl->size = 0;
|
||||||
if (buffer == NULL || capacity == 0) {
|
message_impl->read_offset = 0;
|
||||||
message_impl->status = MESSAGE_STATUS_NOT_INITIALIZED;
|
message_impl->status = MESSAGE_STATUS_OK;
|
||||||
}
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Erase the contents of the message, set it to an empty state by setting the
|
* Erase the contents of the message, set it to an empty state by setting the
|
||||||
* message size and read offset to 0, effectively erasing the contents of the
|
* message size and read offset to 0, effectively erasing the contents of the
|
||||||
* message. The message data buffer pointer remains unchanged, i.e. the message
|
* message. The message data buffer pointer remains unchanged, i.e. the message
|
||||||
* retains ownership of the buffer. The message status is reset to
|
* retains ownership of the buffer. The message buffer is zero-filled. The
|
||||||
* MESSAGE_STATUS_OK.
|
* message status is reset to MESSAGE_STATUS_OK.
|
||||||
*/
|
*/
|
||||||
void ODK_Message_Clear(ODK_Message* message) {
|
void ODK_Message_Clear(ODK_Message* message) {
|
||||||
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
assert(message_impl != NULL);
|
assert(message_impl != NULL);
|
||||||
ODK_Message_Reset(message);
|
message_impl->read_offset = 0;
|
||||||
message_impl->size = 0;
|
message_impl->size = 0;
|
||||||
|
message_impl->status = MESSAGE_STATUS_OK;
|
||||||
|
if (message_impl->base) {
|
||||||
|
memset(message_impl->base, 0, message_impl->capacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -122,7 +128,10 @@ ODK_MessageStatus ODK_Message_GetStatus(ODK_Message* message) {
|
|||||||
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status) {
|
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status) {
|
||||||
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
assert(message_impl != NULL);
|
assert(message_impl != NULL);
|
||||||
message_impl->status = status;
|
/* preserve the first error */
|
||||||
|
if (message_impl->status == MESSAGE_STATUS_OK) {
|
||||||
|
message_impl->status = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -132,13 +141,15 @@ void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status) {
|
|||||||
void ODK_Message_SetSize(ODK_Message* message, size_t size) {
|
void ODK_Message_SetSize(ODK_Message* message, size_t size) {
|
||||||
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
assert(message_impl != NULL);
|
assert(message_impl != NULL);
|
||||||
|
assert(size <= message_impl->capacity);
|
||||||
message_impl->size = size;
|
message_impl->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test if the integrity of a message. This means that the status must be
|
* Test if the integrity of a message. This means that the status must be
|
||||||
* MESSAGE_STATUS_OK and that the base, read_offset, size and capacity of the
|
* MESSAGE_STATUS_OK and that the base, read_offset, size and capacity of the
|
||||||
* message are within the range of valid values.
|
* message are within the range of valid values. The message's base pointer
|
||||||
|
* may be NULL if the buffer has not been assigned yet, that is not invalid.
|
||||||
*/
|
*/
|
||||||
bool ODK_Message_IsValid(ODK_Message* message) {
|
bool ODK_Message_IsValid(ODK_Message* message) {
|
||||||
assert(message);
|
assert(message);
|
||||||
@@ -149,10 +160,6 @@ bool ODK_Message_IsValid(ODK_Message* message) {
|
|||||||
if (message_impl->status != MESSAGE_STATUS_OK) {
|
if (message_impl->status != MESSAGE_STATUS_OK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (message_impl->base == NULL) {
|
|
||||||
message_impl->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (message_impl->read_offset > message_impl->capacity ||
|
if (message_impl->read_offset > message_impl->capacity ||
|
||||||
message_impl->size > message_impl->capacity ||
|
message_impl->size > message_impl->capacity ||
|
||||||
message_impl->read_offset > message_impl->size) {
|
message_impl->read_offset > message_impl->size) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_
|
#ifndef WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -34,3 +34,13 @@ int odk_add_overflow_ux(size_t a, size_t b, size_t* c) {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int odk_mul_overflow_ux(size_t a, size_t b, size_t* c) {
|
||||||
|
if (b > 0 && a > SIZE_MAX / b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (c) {
|
||||||
|
*c = a * b;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
|
#ifndef WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
|
||||||
@@ -15,6 +15,7 @@ extern "C" {
|
|||||||
int odk_sub_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
int odk_sub_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
||||||
int odk_add_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
int odk_add_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
||||||
int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
|
int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
|
||||||
|
int odk_mul_overflow_ux(size_t a, size_t b, size_t* c);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -58,6 +58,47 @@ static void Pack_ODK_ParsedLicense(ODK_Message* msg,
|
|||||||
Pack_enum(msg, obj->license_type);
|
Pack_enum(msg, obj->license_type);
|
||||||
Pack_bool(msg, &obj->nonce_required);
|
Pack_bool(msg, &obj->nonce_required);
|
||||||
Pack_ODK_TimerLimits(msg, &obj->timer_limits);
|
Pack_ODK_TimerLimits(msg, &obj->timer_limits);
|
||||||
|
Pack_uint32_t(msg, &obj->watermarking);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.dtcp2_required);
|
||||||
|
if (obj->dtcp2_required.dtcp2_required) {
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_0.id);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_0.extension);
|
||||||
|
Pack_uint16_t(msg, &obj->dtcp2_required.cmi_descriptor_0.length);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_0.data);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.id);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.extension);
|
||||||
|
Pack_uint16_t(msg, &obj->dtcp2_required.cmi_descriptor_1.length);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.data[0]);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.data[1]);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.data[2]);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.id);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.extension);
|
||||||
|
Pack_uint16_t(msg, &obj->dtcp2_required.cmi_descriptor_2.length);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.data[0]);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.data[1]);
|
||||||
|
Pack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.data[2]);
|
||||||
|
}
|
||||||
|
Pack_uint32_t(msg, &obj->key_array_length);
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < (size_t)obj->key_array_length; i++) {
|
||||||
|
Pack_OEMCrypto_KeyObject(msg, &obj->key_array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Pack_ODK_ParsedLicenseV16(ODK_Message* msg,
|
||||||
|
ODK_ParsedLicenseV16 const* obj) {
|
||||||
|
/* hand-coded */
|
||||||
|
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||||
|
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
|
||||||
|
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
|
||||||
|
Pack_OEMCrypto_Substring(msg, &obj->pst);
|
||||||
|
Pack_OEMCrypto_Substring(msg, &obj->srm_restriction_data);
|
||||||
|
Pack_enum(msg, obj->license_type);
|
||||||
|
Pack_bool(msg, &obj->nonce_required);
|
||||||
|
Pack_ODK_TimerLimits(msg, &obj->timer_limits);
|
||||||
Pack_uint32_t(msg, &obj->key_array_length);
|
Pack_uint32_t(msg, &obj->key_array_length);
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < (size_t)obj->key_array_length; i++) {
|
for (i = 0; i < (size_t)obj->key_array_length; i++) {
|
||||||
@@ -87,18 +128,34 @@ void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Pack_ODK_PreparedProvisioningRequest(
|
void Pack_ODK_PreparedProvisioningRequest(
|
||||||
ODK_Message* msg, ODK_PreparedProvisioningRequest const* obj) {
|
ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj) {
|
||||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
Pack_uint32_t(msg, &obj->device_id_length);
|
Pack_uint32_t(msg, &obj->device_id_length);
|
||||||
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pack_ODK_PreparedRenewedProvisioningRequest(
|
||||||
|
ODK_Message* msg, const ODK_PreparedRenewedProvisioningRequest* obj) {
|
||||||
|
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
|
Pack_uint32_t(msg, &obj->device_id_length);
|
||||||
|
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||||
|
Pack_uint16_t(msg, &obj->renewal_type);
|
||||||
|
Pack_uint32_t(msg, &obj->renewal_data_length);
|
||||||
|
PackArray(msg, &obj->renewal_data[0], sizeof(obj->renewal_data));
|
||||||
|
}
|
||||||
|
|
||||||
/* @@ kdo serialize */
|
/* @@ kdo serialize */
|
||||||
|
|
||||||
void Pack_ODK_LicenseResponse(ODK_Message* msg,
|
void Pack_ODK_LicenseResponse(ODK_Message* msg,
|
||||||
ODK_LicenseResponse const* obj) {
|
ODK_LicenseResponse const* obj) {
|
||||||
Pack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
Pack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
||||||
Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
|
Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pack_ODK_LicenseResponseV16(ODK_Message* msg,
|
||||||
|
ODK_LicenseResponseV16 const* obj) {
|
||||||
|
Pack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
||||||
|
Pack_ODK_ParsedLicenseV16(msg, &obj->parsed_license);
|
||||||
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +166,7 @@ void Pack_ODK_RenewalResponse(ODK_Message* msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
ODK_ProvisioningResponse const* obj) {
|
const ODK_ProvisioningResponse* obj) {
|
||||||
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||||
Pack_ODK_ParsedProvisioning(
|
Pack_ODK_ParsedProvisioning(
|
||||||
msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning);
|
msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning);
|
||||||
@@ -126,7 +183,7 @@ static void Unpack_ODK_NonceValues(ODK_Message* msg, ODK_NonceValues* obj) {
|
|||||||
Unpack_uint32_t(msg, &obj->session_id);
|
Unpack_uint32_t(msg, &obj->session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Unpack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage* obj) {
|
void Unpack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage* obj) {
|
||||||
Unpack_uint32_t(msg, &obj->message_type);
|
Unpack_uint32_t(msg, &obj->message_type);
|
||||||
Unpack_uint32_t(msg, &obj->message_length);
|
Unpack_uint32_t(msg, &obj->message_length);
|
||||||
Unpack_ODK_NonceValues(msg, &obj->nonce_values);
|
Unpack_ODK_NonceValues(msg, &obj->nonce_values);
|
||||||
@@ -158,6 +215,64 @@ static void Unpack_ODK_ParsedLicense(ODK_Message* msg, ODK_ParsedLicense* obj) {
|
|||||||
obj->license_type = (OEMCrypto_LicenseType)Unpack_enum(msg);
|
obj->license_type = (OEMCrypto_LicenseType)Unpack_enum(msg);
|
||||||
Unpack_bool(msg, &obj->nonce_required);
|
Unpack_bool(msg, &obj->nonce_required);
|
||||||
Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
|
Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
|
||||||
|
Unpack_uint32_t(msg, &obj->watermarking);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.dtcp2_required);
|
||||||
|
if (obj->dtcp2_required.dtcp2_required) {
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_0.id);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_0.extension);
|
||||||
|
Unpack_uint16_t(msg, &obj->dtcp2_required.cmi_descriptor_0.length);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_0.data);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.id);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.extension);
|
||||||
|
Unpack_uint16_t(msg, &obj->dtcp2_required.cmi_descriptor_1.length);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.data[0]);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.data[1]);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_1.data[2]);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.id);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.extension);
|
||||||
|
Unpack_uint16_t(msg, &obj->dtcp2_required.cmi_descriptor_2.length);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.data[0]);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.data[1]);
|
||||||
|
Unpack_uint8_t(msg, &obj->dtcp2_required.cmi_descriptor_2.data[2]);
|
||||||
|
} else {
|
||||||
|
obj->dtcp2_required.dtcp2_required = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_0.id = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_0.extension = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_0.length = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_0.data = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_1.id = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_1.extension = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_1.length = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_1.data[0] = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_1.data[1] = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_1.data[2] = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_2.id = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_2.extension = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_2.length = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_2.data[0] = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_2.data[1] = 0;
|
||||||
|
obj->dtcp2_required.cmi_descriptor_2.data[2] = 0;
|
||||||
|
}
|
||||||
|
Unpack_uint32_t(msg, &obj->key_array_length);
|
||||||
|
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||||
|
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < obj->key_array_length; i++) {
|
||||||
|
Unpack_OEMCrypto_KeyObject(msg, &obj->key_array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Unpack_ODK_ParsedLicenseV16(ODK_Message* msg,
|
||||||
|
ODK_ParsedLicenseV16* obj) {
|
||||||
|
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
|
||||||
|
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
|
||||||
|
Unpack_OEMCrypto_Substring(msg, &obj->pst);
|
||||||
|
Unpack_OEMCrypto_Substring(msg, &obj->srm_restriction_data);
|
||||||
|
obj->license_type = (OEMCrypto_LicenseType)Unpack_enum(msg);
|
||||||
|
Unpack_bool(msg, &obj->nonce_required);
|
||||||
|
Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
|
||||||
Unpack_uint32_t(msg, &obj->key_array_length);
|
Unpack_uint32_t(msg, &obj->key_array_length);
|
||||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||||
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||||
@@ -197,6 +312,16 @@ void Unpack_ODK_PreparedProvisioningRequest(
|
|||||||
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unpack_ODK_PreparedRenewedProvisioningRequest(
|
||||||
|
ODK_Message* msg, ODK_PreparedRenewedProvisioningRequest* obj) {
|
||||||
|
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
|
Unpack_uint32_t(msg, &obj->device_id_length);
|
||||||
|
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||||
|
Unpack_uint16_t(msg, &obj->renewal_type);
|
||||||
|
Unpack_uint32_t(msg, &obj->renewal_data_length);
|
||||||
|
UnpackArray(msg, &obj->renewal_data[0], obj->renewal_data_length);
|
||||||
|
}
|
||||||
|
|
||||||
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
||||||
ODK_PreparedCommonRequest* obj) {
|
ODK_PreparedCommonRequest* obj) {
|
||||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
@@ -206,6 +331,12 @@ void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
|||||||
void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj) {
|
void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj) {
|
||||||
Unpack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
Unpack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
||||||
Unpack_ODK_ParsedLicense(msg, obj->parsed_license);
|
Unpack_ODK_ParsedLicense(msg, obj->parsed_license);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unpack_ODK_LicenseResponseV16(ODK_Message* msg,
|
||||||
|
ODK_LicenseResponseV16* obj) {
|
||||||
|
Unpack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
||||||
|
Unpack_ODK_ParsedLicenseV16(msg, &obj->parsed_license);
|
||||||
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -22,15 +22,22 @@ void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
|||||||
const ODK_PreparedRenewalRequest* obj);
|
const ODK_PreparedRenewalRequest* obj);
|
||||||
void Pack_ODK_PreparedProvisioningRequest(
|
void Pack_ODK_PreparedProvisioningRequest(
|
||||||
ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
||||||
|
void Pack_ODK_PreparedRenewedProvisioningRequest(
|
||||||
|
ODK_Message* msg, const ODK_PreparedRenewedProvisioningRequest* obj);
|
||||||
|
|
||||||
/* odk unpack */
|
/* 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_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj);
|
||||||
|
void Unpack_ODK_LicenseResponseV16(ODK_Message* msg,
|
||||||
|
ODK_LicenseResponseV16* obj);
|
||||||
void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj);
|
void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj);
|
||||||
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
ODK_ProvisioningResponse* obj);
|
ODK_ProvisioningResponse* obj);
|
||||||
|
|
||||||
/* kdo pack */
|
/* kdo pack */
|
||||||
void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_LicenseResponse* obj);
|
void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_LicenseResponse* obj);
|
||||||
|
void Pack_ODK_LicenseResponseV16(ODK_Message* msg,
|
||||||
|
const ODK_LicenseResponseV16* obj);
|
||||||
void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj);
|
void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj);
|
||||||
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
const ODK_ProvisioningResponse* obj);
|
const ODK_ProvisioningResponse* obj);
|
||||||
@@ -42,6 +49,8 @@ void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
|||||||
ODK_PreparedRenewalRequest* obj);
|
ODK_PreparedRenewalRequest* obj);
|
||||||
void Unpack_ODK_PreparedProvisioningRequest(
|
void Unpack_ODK_PreparedProvisioningRequest(
|
||||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
|
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
|
||||||
|
void Unpack_ODK_PreparedRenewedProvisioningRequest(
|
||||||
|
ODK_Message* msg, ODK_PreparedRenewedProvisioningRequest* obj);
|
||||||
|
|
||||||
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
||||||
ODK_PreparedCommonRequest* obj);
|
ODK_PreparedCommonRequest* obj);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
|
#ifndef WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
|
||||||
@@ -24,6 +24,7 @@ typedef uint32_t ODK_MessageType;
|
|||||||
#define ODK_Renewal_Response_Type ((ODK_MessageType)4u)
|
#define ODK_Renewal_Response_Type ((ODK_MessageType)4u)
|
||||||
#define ODK_Provisioning_Request_Type ((ODK_MessageType)5u)
|
#define ODK_Provisioning_Request_Type ((ODK_MessageType)5u)
|
||||||
#define ODK_Provisioning_Response_Type ((ODK_MessageType)6u)
|
#define ODK_Provisioning_Response_Type ((ODK_MessageType)6u)
|
||||||
|
#define ODK_Renewed_Provisioning_Request_Type ((ODK_MessageType)11u)
|
||||||
|
|
||||||
// Reserve future message types to support forward compatibility.
|
// Reserve future message types to support forward compatibility.
|
||||||
#define ODK_Release_Request_Type ((ODK_MessageType)7u)
|
#define ODK_Release_Request_Type ((ODK_MessageType)7u)
|
||||||
@@ -32,8 +33,8 @@ typedef uint32_t ODK_MessageType;
|
|||||||
#define ODK_Common_Response_Type ((ODK_MessageType)10u)
|
#define ODK_Common_Response_Type ((ODK_MessageType)10u)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ODK_MessageType message_type;
|
ODK_MessageType message_type; // Type of core message (defined above)
|
||||||
uint32_t message_length;
|
uint32_t message_length; // Length of core message.
|
||||||
ODK_NonceValues nonce_values;
|
ODK_NonceValues nonce_values;
|
||||||
} ODK_CoreMessage;
|
} ODK_CoreMessage;
|
||||||
|
|
||||||
@@ -52,16 +53,42 @@ typedef struct {
|
|||||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
|
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
|
||||||
} ODK_PreparedProvisioningRequest;
|
} ODK_PreparedProvisioningRequest;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ODK_CoreMessage core_message;
|
||||||
|
uint32_t device_id_length;
|
||||||
|
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
|
||||||
|
uint16_t renewal_type;
|
||||||
|
uint32_t renewal_data_length;
|
||||||
|
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE];
|
||||||
|
} ODK_PreparedRenewedProvisioningRequest;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ODK_CoreMessage core_message;
|
ODK_CoreMessage core_message;
|
||||||
} ODK_PreparedCommonRequest;
|
} ODK_PreparedCommonRequest;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OEMCrypto_Substring enc_mac_keys_iv;
|
||||||
|
OEMCrypto_Substring enc_mac_keys;
|
||||||
|
OEMCrypto_Substring pst;
|
||||||
|
OEMCrypto_Substring srm_restriction_data;
|
||||||
|
OEMCrypto_LicenseType license_type;
|
||||||
|
bool nonce_required;
|
||||||
|
ODK_TimerLimits timer_limits;
|
||||||
|
uint32_t key_array_length;
|
||||||
|
OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
|
||||||
|
} ODK_ParsedLicenseV16;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ODK_PreparedLicenseRequest request;
|
ODK_PreparedLicenseRequest request;
|
||||||
ODK_ParsedLicense* parsed_license;
|
ODK_ParsedLicense* parsed_license;
|
||||||
uint8_t request_hash[ODK_SHA256_HASH_SIZE];
|
|
||||||
} ODK_LicenseResponse;
|
} ODK_LicenseResponse;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ODK_PreparedLicenseRequest request;
|
||||||
|
ODK_ParsedLicenseV16 parsed_license;
|
||||||
|
uint8_t request_hash[ODK_SHA256_HASH_SIZE];
|
||||||
|
} ODK_LicenseResponseV16;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ODK_PreparedRenewalRequest request;
|
ODK_PreparedRenewalRequest request;
|
||||||
uint64_t renewal_duration_seconds;
|
uint64_t renewal_duration_seconds;
|
||||||
@@ -76,26 +103,27 @@ typedef struct {
|
|||||||
// without any padding added by the compiler. Make sure they get updated when
|
// without any padding added by the compiler. Make sure they get updated when
|
||||||
// request structs change. Refer to test suite OdkSizeTest in
|
// request structs change. Refer to test suite OdkSizeTest in
|
||||||
// ../test/odk_test.cpp for validations of each of the defined request sizes.
|
// ../test/odk_test.cpp for validations of each of the defined request sizes.
|
||||||
#define ODK_LICENSE_REQUEST_SIZE 20
|
#define ODK_LICENSE_REQUEST_SIZE 20u
|
||||||
#define ODK_RENEWAL_REQUEST_SIZE 28
|
#define ODK_RENEWAL_REQUEST_SIZE 28u
|
||||||
#define ODK_PROVISIONING_REQUEST_SIZE 88
|
#define ODK_PROVISIONING_REQUEST_SIZE 88u
|
||||||
|
#define ODK_RENEWED_PROVISIONING_REQUEST_SIZE 1694u
|
||||||
|
|
||||||
// These are the possible timer status values.
|
// These are the possible timer status values.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 // Should not happen.
|
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0u // Should not happen.
|
||||||
// When the structure has been initialized, but no license is loaded.
|
// When the structure has been initialized, but no license is loaded.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED 1
|
#define ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED 1u
|
||||||
// After the license is loaded, before a successful decrypt.
|
// After the license is loaded, before a successful decrypt.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED 2
|
#define ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED 2u
|
||||||
// After the license is loaded, if a renewal has also been loaded.
|
// After the license is loaded, if a renewal has also been loaded.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED 3
|
#define ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED 3u
|
||||||
// The first decrypt has occurred and the timer is active.
|
// The first decrypt has occurred and the timer is active.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_ACTIVE 4
|
#define ODK_CLOCK_TIMER_STATUS_ACTIVE 4u
|
||||||
// The first decrypt has occurred and the timer is unlimited.
|
// The first decrypt has occurred and the timer is unlimited.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_UNLIMITED 5
|
#define ODK_CLOCK_TIMER_STATUS_UNLIMITED 5u
|
||||||
// The timer has transitioned from active to expired.
|
// The timer has transitioned from active to expired.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_EXPIRED 6
|
#define ODK_CLOCK_TIMER_STATUS_EXPIRED 6u
|
||||||
// The license has been marked as inactive.
|
// The license has been marked as inactive.
|
||||||
#define ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE 7
|
#define ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE 7u
|
||||||
|
|
||||||
// A helper function for computing timer limits when a renewal is loaded.
|
// A helper function for computing timer limits when a renewal is loaded.
|
||||||
OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -71,7 +71,7 @@ static OEMCryptoResult ODK_CheckRentalWindow(
|
|||||||
/* rental_clock = time since license signed. */
|
/* rental_clock = time since license signed. */
|
||||||
uint64_t rental_clock = 0;
|
uint64_t rental_clock = 0;
|
||||||
if (odk_sub_overflow_u64(system_time_seconds,
|
if (odk_sub_overflow_u64(system_time_seconds,
|
||||||
clock_values->time_of_license_signed,
|
clock_values->time_of_license_request_signed,
|
||||||
&rental_clock)) {
|
&rental_clock)) {
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
|||||||
}
|
}
|
||||||
/* If this is before the license was signed, something is odd. Return an
|
/* If this is before the license was signed, something is odd. Return an
|
||||||
* error. */
|
* error. */
|
||||||
if (system_time_seconds < clock_values->time_of_license_signed) {
|
if (system_time_seconds < clock_values->time_of_license_request_signed) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
|||||||
if (clock_values == NULL) {
|
if (clock_values == NULL) {
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
clock_values->time_of_license_signed = system_time_seconds;
|
clock_values->time_of_license_request_signed = system_time_seconds;
|
||||||
clock_values->time_of_first_decrypt = 0;
|
clock_values->time_of_first_decrypt = 0;
|
||||||
clock_values->time_of_last_decrypt = 0;
|
clock_values->time_of_last_decrypt = 0;
|
||||||
clock_values->time_when_timer_expires = 0;
|
clock_values->time_when_timer_expires = 0;
|
||||||
@@ -308,7 +308,7 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
|
|||||||
|
|
||||||
/* This is called when OEMCrypto reloads a usage entry. */
|
/* This is called when OEMCrypto reloads a usage entry. */
|
||||||
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
||||||
uint64_t time_of_license_signed,
|
uint64_t time_of_license_request_signed,
|
||||||
uint64_t time_of_first_decrypt,
|
uint64_t time_of_first_decrypt,
|
||||||
uint64_t time_of_last_decrypt,
|
uint64_t time_of_last_decrypt,
|
||||||
enum OEMCrypto_Usage_Entry_Status status,
|
enum OEMCrypto_Usage_Entry_Status status,
|
||||||
@@ -316,7 +316,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
|||||||
if (clock_values == NULL) {
|
if (clock_values == NULL) {
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
clock_values->time_of_license_signed = time_of_license_signed;
|
clock_values->time_of_license_request_signed = time_of_license_request_signed;
|
||||||
clock_values->time_of_first_decrypt = time_of_first_decrypt;
|
clock_values->time_of_first_decrypt = time_of_first_decrypt;
|
||||||
clock_values->time_of_last_decrypt = time_of_last_decrypt;
|
clock_values->time_of_last_decrypt = time_of_last_decrypt;
|
||||||
clock_values->time_when_timer_expires = 0;
|
clock_values->time_when_timer_expires = 0;
|
||||||
@@ -336,7 +336,7 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
|
|||||||
/* All times are relative to when the license was signed. */
|
/* All times are relative to when the license was signed. */
|
||||||
uint64_t rental_time = 0;
|
uint64_t rental_time = 0;
|
||||||
if (odk_sub_overflow_u64(system_time_seconds,
|
if (odk_sub_overflow_u64(system_time_seconds,
|
||||||
clock_values->time_of_license_signed,
|
clock_values->time_of_license_request_signed,
|
||||||
&rental_time)) {
|
&rental_time)) {
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "odk_util.h"
|
#include "odk_util.h"
|
||||||
@@ -24,11 +24,10 @@ int crypto_memcmp(const void* in_a, const void* in_b, size_t len) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b) {
|
bool ODK_NonceValuesEqualExcludingVersion(const ODK_NonceValues* a,
|
||||||
|
const ODK_NonceValues* b) {
|
||||||
if (a == NULL || b == NULL) {
|
if (a == NULL || b == NULL) {
|
||||||
return (a == b);
|
return (a == b);
|
||||||
}
|
}
|
||||||
return (a->api_major_version == b->api_major_version &&
|
return (a->nonce == b->nonce && a->session_id == b->session_id);
|
||||||
a->api_minor_version == b->api_minor_version &&
|
|
||||||
a->nonce == b->nonce && a->session_id == b->session_id);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_ODK_UTIL_H_
|
#ifndef WIDEVINE_ODK_SRC_ODK_UTIL_H_
|
||||||
@@ -20,7 +20,8 @@ extern "C" {
|
|||||||
* return value when a != b is undefined, other than being non-zero. */
|
* return value when a != b is undefined, other than being non-zero. */
|
||||||
int crypto_memcmp(const void* a, const void* b, size_t len);
|
int crypto_memcmp(const void* a, const void* b, size_t len);
|
||||||
|
|
||||||
bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b);
|
bool ODK_NonceValuesEqualExcludingVersion(const ODK_NonceValues* a,
|
||||||
|
const ODK_NonceValues* b);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "serialization_base.h"
|
#include "serialization_base.h"
|
||||||
@@ -29,7 +29,8 @@ static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
|
|||||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||||
if (!message_impl) return;
|
if (!message_impl) return;
|
||||||
if (count <= message_impl->capacity - message_impl->size) {
|
if (count <= message_impl->capacity - message_impl->size) {
|
||||||
memcpy((void*)(message_impl->base + message_impl->size), (void*)ptr, count);
|
memcpy((void*)(message_impl->base + message_impl->size), (const void*)ptr,
|
||||||
|
count);
|
||||||
message_impl->size += count;
|
message_impl->size += count;
|
||||||
} else {
|
} else {
|
||||||
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||||
@@ -37,7 +38,7 @@ static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Pack_enum(ODK_Message* message, int value) {
|
void Pack_enum(ODK_Message* message, int value) {
|
||||||
uint32_t v32 = value;
|
uint32_t v32 = (uint32_t)value;
|
||||||
Pack_uint32_t(message, &v32);
|
Pack_uint32_t(message, &v32);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +49,13 @@ void Pack_bool(ODK_Message* message, const bool* value) {
|
|||||||
PackBytes(message, data, sizeof(data));
|
PackBytes(message, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pack_uint8_t(ODK_Message* message, const uint8_t* value) {
|
||||||
|
assert(value);
|
||||||
|
uint8_t data[1] = {0};
|
||||||
|
data[0] = (uint8_t)(*value >> 0);
|
||||||
|
PackBytes(message, data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
|
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
|
||||||
assert(value);
|
assert(value);
|
||||||
uint8_t data[2] = {0};
|
uint8_t data[2] = {0};
|
||||||
@@ -113,6 +121,13 @@ void Unpack_bool(ODK_Message* message, bool* value) {
|
|||||||
*value = (0 != data[3]);
|
*value = (0 != data[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unpack_uint8_t(ODK_Message* message, uint8_t* value) {
|
||||||
|
assert(value);
|
||||||
|
uint8_t data[1] = {0};
|
||||||
|
UnpackBytes(message, data, sizeof(data));
|
||||||
|
*value = data[0];
|
||||||
|
}
|
||||||
|
|
||||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
|
void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
|
||||||
assert(value);
|
assert(value);
|
||||||
uint8_t data[2] = {0};
|
uint8_t data[2] = {0};
|
||||||
@@ -154,10 +169,18 @@ void Unpack_OEMCrypto_Substring(ODK_Message* message,
|
|||||||
/* Each substring should be contained within the message body, which is in the
|
/* Each substring should be contained within the message body, which is in the
|
||||||
* total message, just after the core message. The offset of a substring is
|
* total message, just after the core message. The offset of a substring is
|
||||||
* relative to the message body. So we need to verify:
|
* relative to the message body. So we need to verify:
|
||||||
* 0 < offset and offset + length < message_impl->capacity -
|
*
|
||||||
* message_impl->size or offset + length + message_impl->size <
|
* For non-empty substring:
|
||||||
* message_impl->capacity
|
* offset + length < message_impl->capacity - message_impl->size or
|
||||||
|
* offset + length + message_impl->size < message_impl->capacity
|
||||||
|
*
|
||||||
|
* For empty substring (length is 0):
|
||||||
|
* offset must be 0
|
||||||
*/
|
*/
|
||||||
|
if (length == 0 && offset != 0) {
|
||||||
|
message_impl->status = MESSAGE_STATUS_UNKNOWN_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
size_t substring_end = 0; /* = offset + length; */
|
size_t substring_end = 0; /* = offset + length; */
|
||||||
size_t end = 0; /* = substring_end + message_impl->size; */
|
size_t end = 0; /* = substring_end + message_impl->size; */
|
||||||
if (odk_add_overflow_ux(offset, length, &substring_end) ||
|
if (odk_add_overflow_ux(offset, length, &substring_end) ||
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
|
#ifndef WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
|
||||||
@@ -17,6 +17,7 @@ extern "C" {
|
|||||||
|
|
||||||
void Pack_enum(ODK_Message* message, int value);
|
void Pack_enum(ODK_Message* message, int value);
|
||||||
void Pack_bool(ODK_Message* message, const bool* value);
|
void Pack_bool(ODK_Message* message, const bool* value);
|
||||||
|
void Pack_uint8_t(ODK_Message* message, const uint8_t* value);
|
||||||
void Pack_uint16_t(ODK_Message* message, const uint16_t* value);
|
void Pack_uint16_t(ODK_Message* message, const uint16_t* value);
|
||||||
void Pack_uint32_t(ODK_Message* message, const uint32_t* value);
|
void Pack_uint32_t(ODK_Message* message, const uint32_t* value);
|
||||||
void Pack_uint64_t(ODK_Message* message, const uint64_t* value);
|
void Pack_uint64_t(ODK_Message* message, const uint64_t* value);
|
||||||
@@ -26,6 +27,7 @@ void Pack_OEMCrypto_Substring(ODK_Message* message,
|
|||||||
|
|
||||||
int Unpack_enum(ODK_Message* message);
|
int Unpack_enum(ODK_Message* message);
|
||||||
void Unpack_bool(ODK_Message* message, bool* value);
|
void Unpack_bool(ODK_Message* message, bool* value);
|
||||||
|
void Unpack_uint8_t(ODK_Message* message, uint8_t* value);
|
||||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value);
|
void Unpack_uint16_t(ODK_Message* message, uint16_t* value);
|
||||||
void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
|
void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
|
||||||
void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
|
void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
|
||||||
|
|||||||
@@ -1,7 +1,19 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
|
// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
|
||||||
|
// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
|
||||||
|
// DEPENDING ON IT IN YOUR PROJECT. ***
|
||||||
|
package {
|
||||||
|
// See: http://go/android-license-faq
|
||||||
|
// A large-scale-change added 'default_applicable_licenses' to import
|
||||||
|
// all of the 'license_kinds' from "vendor_widevine_license"
|
||||||
|
// to get the below license kinds:
|
||||||
|
// legacy_by_exception_only (by exception only)
|
||||||
|
default_applicable_licenses: ["vendor_widevine_license"],
|
||||||
|
}
|
||||||
|
|
||||||
cc_defaults {
|
cc_defaults {
|
||||||
name: "odk_fuzz_library_defaults",
|
name: "odk_fuzz_library_defaults",
|
||||||
srcs: [
|
srcs: [
|
||||||
@@ -165,4 +177,4 @@ cc_fuzz {
|
|||||||
],
|
],
|
||||||
defaults: ["odk_fuzz_library_defaults"],
|
defaults: ["odk_fuzz_library_defaults"],
|
||||||
proprietary: true,
|
proprietary: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
@@ -9,6 +9,18 @@
|
|||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// Builds libwv_odk.so, The ODK shared Library (libwv_odk) is used
|
// Builds libwv_odk.so, The ODK shared Library (libwv_odk) is used
|
||||||
// by the OEMCrypto unit tests to generate corpus for ODK fuzz scrips.
|
// by the OEMCrypto unit tests to generate corpus for ODK fuzz scrips.
|
||||||
|
// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
|
||||||
|
// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
|
||||||
|
// DEPENDING ON IT IN YOUR PROJECT. ***
|
||||||
|
package {
|
||||||
|
// See: http://go/android-license-faq
|
||||||
|
// A large-scale-change added 'default_applicable_licenses' to import
|
||||||
|
// all of the 'license_kinds' from "vendor_widevine_license"
|
||||||
|
// to get the below license kinds:
|
||||||
|
// legacy_by_exception_only (by exception only)
|
||||||
|
default_applicable_licenses: ["vendor_widevine_license"],
|
||||||
|
}
|
||||||
|
|
||||||
cc_library_shared {
|
cc_library_shared {
|
||||||
name: "libwv_odk_corpus_generator",
|
name: "libwv_odk_corpus_generator",
|
||||||
include_dirs: [
|
include_dirs: [
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
// We must define this macro to get RTLD_NEXT definition from <dlfcn.h>
|
// We must define this macro to get RTLD_NEXT definition from <dlfcn.h>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
#include "fuzzing/corpus_generator/odk_corpus_generator_helper.h"
|
#include "fuzzing/corpus_generator/odk_corpus_generator_helper.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
#ifndef WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
|
#ifndef WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
|
||||||
#define WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
|
#define WIDEVINE_ODK_TEST_FUZZING_CORPUS_GENERATOR_ODK_CORPUS_GENERATOR_HELPER_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
# Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
# source code may only be used and distributed under the Widevine Master License
|
# source code may only be used and distributed under the Widevine License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
# Reference Link explaining flags for LD_PRELOAD: https://catonmat.net/simple-ld-preload-tutorial-part-two
|
# Reference Link explaining flags for LD_PRELOAD: https://catonmat.net/simple-ld-preload-tutorial-part-two
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
# source code may only be used and distributed under the Widevine Master License
|
# source code may only be used and distributed under the Widevine License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
#TODO(b/151858867): Fix File paths
|
#TODO(b/151858867): Fix File paths
|
||||||
@@ -18,6 +18,10 @@
|
|||||||
'../src',
|
'../src',
|
||||||
'../kdo/include',
|
'../kdo/include',
|
||||||
],
|
],
|
||||||
|
'cflags': [
|
||||||
|
# TODO(b/172518513): Remove this
|
||||||
|
'-Wno-error=cast-qual',
|
||||||
|
],
|
||||||
'cflags_cc': [
|
'cflags_cc': [
|
||||||
'-std=c++11',
|
'-std=c++11',
|
||||||
'-g3',
|
'-g3',
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
#include "fuzzing/odk_fuzz_helper.h"
|
#include "fuzzing/odk_fuzz_helper.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
|
using features::CoreMessageFeatures;
|
||||||
|
|
||||||
bool convert_byte_to_valid_boolean(const bool* in) {
|
bool convert_byte_to_valid_boolean(const bool* in) {
|
||||||
const char* buf = reinterpret_cast<const char*>(in);
|
const char* buf = reinterpret_cast<const char*>(in);
|
||||||
@@ -67,8 +70,8 @@ OEMCryptoResult odk_deserialize_LicenseResponse(const uint8_t* message,
|
|||||||
return ODK_ParseLicense(message, SIZE_MAX, core_message_length,
|
return ODK_ParseLicense(message, SIZE_MAX, core_message_length,
|
||||||
static_cast<bool>(a->initial_license_load),
|
static_cast<bool>(a->initial_license_load),
|
||||||
static_cast<bool>(a->usage_entry_present),
|
static_cast<bool>(a->usage_entry_present),
|
||||||
a->request_hash, &a->timer_limits, &a->clock_values,
|
&a->timer_limits, &a->clock_values, nonce_values,
|
||||||
nonce_values, parsed_lic);
|
parsed_lic);
|
||||||
}
|
}
|
||||||
|
|
||||||
OEMCryptoResult odk_deserialize_RenewalResponse(
|
OEMCryptoResult odk_deserialize_RenewalResponse(
|
||||||
@@ -122,7 +125,8 @@ bool kdo_serialize_LicenseResponse(const ODK_ParseLicense_Args* args,
|
|||||||
std::string core_request_sha_256(
|
std::string core_request_sha_256(
|
||||||
reinterpret_cast<const char*>(args->request_hash), ODK_SHA256_HASH_SIZE);
|
reinterpret_cast<const char*>(args->request_hash), ODK_SHA256_HASH_SIZE);
|
||||||
return serialize::CreateCoreLicenseResponse(
|
return serialize::CreateCoreLicenseResponse(
|
||||||
parsed_lic, core_request, core_request_sha_256, oemcrypto_core_message);
|
CoreMessageFeatures::kDefaultFeatures, parsed_lic, core_request,
|
||||||
|
core_request_sha_256, oemcrypto_core_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool kdo_serialize_RenewalResponse(
|
bool kdo_serialize_RenewalResponse(
|
||||||
@@ -134,7 +138,8 @@ bool kdo_serialize_RenewalResponse(
|
|||||||
nonce_values.api_minor_version, nonce_values.api_major_version,
|
nonce_values.api_minor_version, nonce_values.api_major_version,
|
||||||
nonce_values.nonce, nonce_values.session_id, renewal_msg.playback_time};
|
nonce_values.nonce, nonce_values.session_id, renewal_msg.playback_time};
|
||||||
return serialize::CreateCoreRenewalResponse(
|
return serialize::CreateCoreRenewalResponse(
|
||||||
core_request, args->timer_limits.initial_renewal_duration_seconds,
|
CoreMessageFeatures::kDefaultFeatures, core_request,
|
||||||
|
args->timer_limits.initial_renewal_duration_seconds,
|
||||||
oemcrypto_core_message);
|
oemcrypto_core_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +156,8 @@ bool kdo_serialize_ProvisioningResponse(
|
|||||||
nonce_values.nonce, nonce_values.session_id,
|
nonce_values.nonce, nonce_values.session_id,
|
||||||
std::string(reinterpret_cast<const char*>(args->device_id),
|
std::string(reinterpret_cast<const char*>(args->device_id),
|
||||||
args->device_id_length)};
|
args->device_id_length)};
|
||||||
return serialize::CreateCoreProvisioningResponse(parsed_prov, core_request,
|
return serialize::CreateCoreProvisioningResponse(
|
||||||
oemcrypto_core_message);
|
CoreMessageFeatures::kDefaultFeatures, parsed_prov, core_request,
|
||||||
|
oemcrypto_core_message);
|
||||||
}
|
}
|
||||||
} // namespace oemcrypto_core_message
|
} // namespace oemcrypto_core_message
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
|
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
|
||||||
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
|
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "core_message_features.h"
|
||||||
#include "core_message_serialize.h"
|
#include "core_message_serialize.h"
|
||||||
#include "fuzzing/odk_fuzz_structs.h"
|
#include "fuzzing/odk_fuzz_structs.h"
|
||||||
#include "odk_attributes.h"
|
#include "odk_attributes.h"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
|
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
|
||||||
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
|
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_STRUCTS_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "fuzzing/odk_fuzz_helper.h"
|
#include "fuzzing/odk_fuzz_helper.h"
|
||||||
|
#include "odk_attributes.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
|
|
||||||
// The custom mutator: Ensure that each input can be deserialized properly
|
// The custom mutator: Ensure that each input can be deserialized properly
|
||||||
// by ODK function after mutation.
|
// by ODK function after mutation.
|
||||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||||
size_t max_size, unsigned int seed) {
|
size_t max_size,
|
||||||
|
unsigned int seed UNUSED) {
|
||||||
const size_t kProvisioningResponseArgsSize =
|
const size_t kProvisioningResponseArgsSize =
|
||||||
sizeof(ODK_ParseProvisioning_Args);
|
sizeof(ODK_ParseProvisioning_Args);
|
||||||
if (size < kProvisioningResponseArgsSize) {
|
if (size < kProvisioningResponseArgsSize) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "fuzzing/odk_fuzz_helper.h"
|
#include "fuzzing/odk_fuzz_helper.h"
|
||||||
|
#include "odk_attributes.h"
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
|
|
||||||
// The custom mutator: Ensure that each input can be deserialized properly
|
// The custom mutator: Ensure that each input can be deserialized properly
|
||||||
// by ODK function after mutation.
|
// by ODK function after mutation.
|
||||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||||
size_t max_size, unsigned int seed) {
|
size_t max_size,
|
||||||
|
unsigned int seed UNUSED) {
|
||||||
const size_t kRenewalResponseArgsSize = sizeof(ODK_ParseRenewal_Args);
|
const size_t kRenewalResponseArgsSize = sizeof(ODK_ParseRenewal_Args);
|
||||||
if (size < kRenewalResponseArgsSize) {
|
if (size < kRenewalResponseArgsSize) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2020 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
|
|
||||||
#include <endian.h> // TODO(b/147944591): use this one? Or odk_endian.h?
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "core_message_deserialize.h"
|
#include "core_message_deserialize.h"
|
||||||
|
#include "core_message_features.h"
|
||||||
#include "core_message_serialize.h"
|
#include "core_message_serialize.h"
|
||||||
#include "core_message_types.h"
|
#include "core_message_types.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
@@ -28,6 +28,10 @@ using oemcrypto_core_message::ODK_RenewalRequest;
|
|||||||
using oemcrypto_core_message::deserialize::CoreLicenseRequestFromMessage;
|
using oemcrypto_core_message::deserialize::CoreLicenseRequestFromMessage;
|
||||||
using oemcrypto_core_message::deserialize::CoreProvisioningRequestFromMessage;
|
using oemcrypto_core_message::deserialize::CoreProvisioningRequestFromMessage;
|
||||||
using oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage;
|
using oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage;
|
||||||
|
using oemcrypto_core_message::deserialize::
|
||||||
|
CoreRenewedProvisioningRequestFromMessage;
|
||||||
|
|
||||||
|
using oemcrypto_core_message::features::CoreMessageFeatures;
|
||||||
|
|
||||||
using oemcrypto_core_message::serialize::CreateCoreLicenseResponse;
|
using oemcrypto_core_message::serialize::CreateCoreLicenseResponse;
|
||||||
using oemcrypto_core_message::serialize::CreateCoreProvisioningResponse;
|
using oemcrypto_core_message::serialize::CreateCoreProvisioningResponse;
|
||||||
@@ -39,12 +43,22 @@ constexpr uint32_t kExtraPayloadSize = 128u;
|
|||||||
* version number, and we will expect the response to have another version
|
* version number, and we will expect the response to have another version
|
||||||
* number. */
|
* number. */
|
||||||
struct VersionParameters {
|
struct VersionParameters {
|
||||||
|
uint32_t maximum_major_version;
|
||||||
uint16_t request_major_version;
|
uint16_t request_major_version;
|
||||||
uint16_t request_minor_version;
|
uint16_t request_minor_version;
|
||||||
uint16_t response_major_version;
|
uint16_t response_major_version;
|
||||||
uint16_t response_minor_version;
|
uint16_t response_minor_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This function is called by GTest when a parameterized test fails in order
|
||||||
|
// to log the parameter used for the failing test.
|
||||||
|
void PrintTo(const VersionParameters& p, std::ostream* os) {
|
||||||
|
*os << "max=v" << p.maximum_major_version << ", request = v"
|
||||||
|
<< p.request_major_version << "." << p.request_minor_version
|
||||||
|
<< ", response = v" << p.response_major_version << "."
|
||||||
|
<< p.response_minor_version;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename F, typename G>
|
template <typename T, typename F, typename G>
|
||||||
void ValidateRequest(uint32_t message_type,
|
void ValidateRequest(uint32_t message_type,
|
||||||
const std::vector<ODK_Field>& extra_fields,
|
const std::vector<ODK_Field>& extra_fields,
|
||||||
@@ -144,11 +158,14 @@ void ValidateResponse(const VersionParameters& versions,
|
|||||||
&bytes_read, extra_fields));
|
&bytes_read, extra_fields));
|
||||||
|
|
||||||
// Parse buf with odk
|
// Parse buf with odk
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS, odk_parse_func(buf, buf_size));
|
const OEMCryptoResult parse_result = odk_parse_func(buf, buf_size);
|
||||||
|
EXPECT_EQ(OEMCrypto_SUCCESS, parse_result);
|
||||||
|
|
||||||
size_t size_out = 0;
|
size_t size_out = 0;
|
||||||
ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf, buf_size, &size_out,
|
if (parse_result != OEMCrypto_SUCCESS) {
|
||||||
extra_fields);
|
ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf, buf_size, &size_out,
|
||||||
|
extra_fields);
|
||||||
|
}
|
||||||
|
|
||||||
// serialize odk output to oemcrypto_core_message
|
// serialize odk output to oemcrypto_core_message
|
||||||
std::string oemcrypto_core_message;
|
std::string oemcrypto_core_message;
|
||||||
@@ -189,15 +206,15 @@ TEST(OdkTest, SerializeFieldsStress) {
|
|||||||
std::srand(0);
|
std::srand(0);
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
fields[i].type = static_cast<ODK_FieldType>(std::rand() %
|
fields[i].type = static_cast<ODK_FieldType>(
|
||||||
static_cast<int>(ODK_NUMTYPES));
|
std::rand() % static_cast<int>(ODK_LAST_STRESSABLE_TYPE));
|
||||||
fields[i].value = malloc(ODK_AllocSize(fields[i].type));
|
fields[i].value = malloc(ODK_AllocSize(fields[i].type));
|
||||||
fields[i].name = "stress";
|
fields[i].name = "stress";
|
||||||
total_size += ODK_FieldLength(fields[i].type);
|
total_size += ODK_FieldLength(fields[i].type);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* buf = new uint8_t[total_size]{};
|
uint8_t* buf = new uint8_t[total_size]{};
|
||||||
for (int i = 0; i < total_size; i++) {
|
for (size_t i = 0; i < total_size; i++) {
|
||||||
buf[i] = std::rand() & 0xff;
|
buf[i] = std::rand() & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +273,41 @@ TEST(OdkTest, NullRequestTest) {
|
|||||||
ODK_PrepareCoreProvisioningRequest(
|
ODK_PrepareCoreProvisioningRequest(
|
||||||
message, ODK_PROVISIONING_REQUEST_SIZE, &core_message_length,
|
message, ODK_PROVISIONING_REQUEST_SIZE, &core_message_length,
|
||||||
&nonce_values, nullptr, 0uL));
|
&nonce_values, nullptr, 0uL));
|
||||||
|
|
||||||
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
nullptr, 0uL, &core_message_length, nullptr, nullptr, 0uL,
|
||||||
|
OEMCrypto_RenewalACert, nullptr, 0uL));
|
||||||
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
nullptr, 0uL, nullptr, &nonce_values, nullptr, 0uL,
|
||||||
|
OEMCrypto_RenewalACert, nullptr, 0uL));
|
||||||
|
|
||||||
|
// Null device id in renewed provisioning request is ok
|
||||||
|
uint8_t renewed_message[ODK_RENEWED_PROVISIONING_REQUEST_SIZE] = {0};
|
||||||
|
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
|
||||||
|
uint32_t renewal_data_length = ODK_KEYBOX_RENEWAL_DATA_SIZE;
|
||||||
|
core_message_length = ODK_RENEWED_PROVISIONING_REQUEST_SIZE;
|
||||||
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
renewed_message, ODK_RENEWED_PROVISIONING_REQUEST_SIZE,
|
||||||
|
&core_message_length, &nonce_values, nullptr, 0uL,
|
||||||
|
OEMCrypto_RenewalACert, renewal_data, renewal_data_length));
|
||||||
|
|
||||||
|
// Null renewal data in renewed provisioning request is ok
|
||||||
|
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||||
|
uint32_t device_id_length = ODK_DEVICE_ID_LEN_MAX;
|
||||||
|
core_message_length = ODK_RENEWED_PROVISIONING_REQUEST_SIZE;
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
renewed_message, ODK_RENEWED_PROVISIONING_REQUEST_SIZE,
|
||||||
|
&core_message_length, &nonce_values, device_id, device_id_length,
|
||||||
|
OEMCrypto_RenewalACert, nullptr, 0uL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OdkTest, NullResponseTest) {
|
TEST(OdkTest, NullResponseTest) {
|
||||||
constexpr size_t message_size = 64;
|
constexpr size_t message_size = 64;
|
||||||
uint8_t message[message_size] = {0};
|
uint8_t message[message_size] = {0};
|
||||||
size_t core_message_length = message_size;
|
size_t core_message_length = message_size;
|
||||||
uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {0};
|
|
||||||
ODK_TimerLimits timer_limits;
|
ODK_TimerLimits timer_limits;
|
||||||
ODK_ParsedLicense parsed_license;
|
ODK_ParsedLicense parsed_license;
|
||||||
ODK_NonceValues nonce_values;
|
ODK_NonceValues nonce_values;
|
||||||
@@ -271,30 +316,26 @@ TEST(OdkTest, NullResponseTest) {
|
|||||||
memset(&clock_values, 0, sizeof(clock_values));
|
memset(&clock_values, 0, sizeof(clock_values));
|
||||||
|
|
||||||
// Assert that nullptr does not cause a core dump.
|
// Assert that nullptr does not cause a core dump.
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
EXPECT_EQ(
|
||||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
ODK_ERROR_CORE_MESSAGE,
|
||||||
true, request_hash, &timer_limits, &clock_values,
|
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||||
&nonce_values, nullptr));
|
&timer_limits, &clock_values, &nonce_values, nullptr));
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
EXPECT_EQ(
|
||||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
ODK_ERROR_CORE_MESSAGE,
|
||||||
true, request_hash, &timer_limits, &clock_values,
|
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||||
nullptr, &parsed_license));
|
&timer_limits, &clock_values, nullptr, &parsed_license));
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
EXPECT_EQ(
|
||||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
ODK_ERROR_CORE_MESSAGE,
|
||||||
true, request_hash, &timer_limits, nullptr,
|
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||||
&nonce_values, &parsed_license));
|
&timer_limits, nullptr, &nonce_values, &parsed_license));
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
EXPECT_EQ(
|
||||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
ODK_ERROR_CORE_MESSAGE,
|
||||||
true, request_hash, nullptr, &clock_values,
|
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||||
&nonce_values, &parsed_license));
|
nullptr, &clock_values, &nonce_values, &parsed_license));
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
|
||||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
|
||||||
true, nullptr, &timer_limits, &clock_values,
|
|
||||||
&nonce_values, &parsed_license));
|
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||||
ODK_ParseLicense(nullptr, message_size, core_message_length, true,
|
ODK_ParseLicense(nullptr, message_size, core_message_length, true,
|
||||||
true, request_hash, &timer_limits, &clock_values,
|
true, &timer_limits, &clock_values, &nonce_values,
|
||||||
&nonce_values, &parsed_license));
|
&parsed_license));
|
||||||
|
|
||||||
constexpr uint64_t system_time = 0;
|
constexpr uint64_t system_time = 0;
|
||||||
uint64_t timer_value = 0;
|
uint64_t timer_value = 0;
|
||||||
@@ -413,6 +454,21 @@ TEST(OdkTest, PrepareCoreProvisioningRequest) {
|
|||||||
&core_message_length, &nonce_values, device_id, sizeof(device_id)));
|
&core_message_length, &nonce_values, device_id, sizeof(device_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(OdkTest, PrepareCoreRenewedProvisioningRequest) {
|
||||||
|
uint8_t provisioning_message[ODK_RENEWED_PROVISIONING_REQUEST_SIZE] = {0};
|
||||||
|
size_t core_message_length = sizeof(provisioning_message);
|
||||||
|
ODK_NonceValues nonce_values;
|
||||||
|
memset(&nonce_values, 0, sizeof(nonce_values));
|
||||||
|
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||||
|
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
|
||||||
|
EXPECT_EQ(
|
||||||
|
OEMCrypto_SUCCESS,
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
provisioning_message, sizeof(provisioning_message),
|
||||||
|
&core_message_length, &nonce_values, device_id, sizeof(device_id),
|
||||||
|
OEMCrypto_RenewalACert, renewal_data, sizeof(renewal_data)));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(OdkTest, PrepareCoreProvisioningRequestDeviceId) {
|
TEST(OdkTest, PrepareCoreProvisioningRequestDeviceId) {
|
||||||
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||||
size_t core_message_length = sizeof(provisioning_message);
|
size_t core_message_length = sizeof(provisioning_message);
|
||||||
@@ -426,6 +482,36 @@ TEST(OdkTest, PrepareCoreProvisioningRequestDeviceId) {
|
|||||||
sizeof(device_id_invalid)));
|
sizeof(device_id_invalid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(OdkTest, PrepareCoreRenewedProvisioningRequestDeviceId) {
|
||||||
|
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||||
|
size_t core_message_length = sizeof(provisioning_message);
|
||||||
|
ODK_NonceValues nonce_values;
|
||||||
|
memset(&nonce_values, 0, sizeof(nonce_values));
|
||||||
|
uint8_t device_id_invalid[ODK_DEVICE_ID_LEN_MAX + 1] = {0};
|
||||||
|
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
|
||||||
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
provisioning_message, sizeof(provisioning_message),
|
||||||
|
&core_message_length, &nonce_values, device_id_invalid,
|
||||||
|
sizeof(device_id_invalid), OEMCrypto_RenewalACert, renewal_data,
|
||||||
|
sizeof(renewal_data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OdkTest, PrepareCoreRenewedProvisioningRequestRenewalDataInvalid) {
|
||||||
|
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
|
||||||
|
size_t core_message_length = sizeof(provisioning_message);
|
||||||
|
ODK_NonceValues nonce_values;
|
||||||
|
memset(&nonce_values, 0, sizeof(nonce_values));
|
||||||
|
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||||
|
uint8_t renewal_data_invalid[ODK_KEYBOX_RENEWAL_DATA_SIZE + 1] = {0};
|
||||||
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||||
|
ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
provisioning_message, sizeof(provisioning_message),
|
||||||
|
&core_message_length, &nonce_values, device_id,
|
||||||
|
sizeof(device_id), OEMCrypto_RenewalACert, renewal_data_invalid,
|
||||||
|
sizeof(renewal_data_invalid)));
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize and de-serialize license request
|
// Serialize and de-serialize license request
|
||||||
TEST(OdkTest, LicenseRequestRoundtrip) {
|
TEST(OdkTest, LicenseRequestRoundtrip) {
|
||||||
std::vector<ODK_Field> empty;
|
std::vector<ODK_Field> empty;
|
||||||
@@ -488,9 +574,42 @@ TEST(OdkTest, ProvisionRequestRoundtrip) {
|
|||||||
kdo_parse_func);
|
kdo_parse_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(OdkTest, RenewedProvisionRequestRoundtrip) {
|
||||||
|
uint32_t device_id_length = ODK_DEVICE_ID_LEN_MAX / 2;
|
||||||
|
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
|
||||||
|
memset(device_id, 0xff, device_id_length);
|
||||||
|
uint16_t renewal_type = OEMCrypto_RenewalACert;
|
||||||
|
uint32_t renewal_data_length = ODK_KEYBOX_RENEWAL_DATA_SIZE / 2;
|
||||||
|
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
|
||||||
|
memset(renewal_data, 0xff, renewal_data_length);
|
||||||
|
std::vector<ODK_Field> extra_fields = {
|
||||||
|
{ODK_UINT32, &device_id_length, "device_id_length"},
|
||||||
|
{ODK_DEVICEID, device_id, "device_id"},
|
||||||
|
{ODK_UINT16, &renewal_type, "renewal_type"},
|
||||||
|
{ODK_UINT32, &renewal_data_length, "renewal_data_length"},
|
||||||
|
{ODK_RENEWALDATA, renewal_data, "renewal_data"},
|
||||||
|
};
|
||||||
|
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
|
||||||
|
const ODK_NonceValues* nonce_values) {
|
||||||
|
return ODK_PrepareCoreRenewedProvisioningRequest(
|
||||||
|
buf, SIZE_MAX, size, nonce_values, device_id, device_id_length,
|
||||||
|
renewal_type, renewal_data, renewal_data_length);
|
||||||
|
};
|
||||||
|
auto kdo_parse_func =
|
||||||
|
[&](const std::string& oemcrypto_core_message,
|
||||||
|
ODK_ProvisioningRequest* core_provisioning_request) {
|
||||||
|
bool ok = CoreRenewedProvisioningRequestFromMessage(
|
||||||
|
oemcrypto_core_message, core_provisioning_request);
|
||||||
|
return ok;
|
||||||
|
};
|
||||||
|
ValidateRequest<ODK_ProvisioningRequest>(
|
||||||
|
ODK_Renewed_Provisioning_Request_Type, extra_fields, odk_prepare_func,
|
||||||
|
kdo_parse_func);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(OdkTest, ParseLicenseErrorNonce) {
|
TEST(OdkTest, ParseLicenseErrorNonce) {
|
||||||
ODK_LicenseResponseParams params;
|
ODK_LicenseResponseParams params;
|
||||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||||
uint8_t* buf = nullptr;
|
uint8_t* buf = nullptr;
|
||||||
uint32_t buf_size = 0;
|
uint32_t buf_size = 0;
|
||||||
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||||
@@ -499,7 +618,7 @@ TEST(OdkTest, ParseLicenseErrorNonce) {
|
|||||||
params.core_message.nonce_values.nonce = 0;
|
params.core_message.nonce_values.nonce = 0;
|
||||||
OEMCryptoResult err = ODK_ParseLicense(
|
OEMCryptoResult err = ODK_ParseLicense(
|
||||||
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||||
params.usage_entry_present, params.request_hash, &(params.timer_limits),
|
params.usage_entry_present, &(params.timer_limits),
|
||||||
&(params.clock_values), &(params.core_message.nonce_values),
|
&(params.clock_values), &(params.core_message.nonce_values),
|
||||||
&(params.parsed_license));
|
&(params.parsed_license));
|
||||||
EXPECT_EQ(OEMCrypto_ERROR_INVALID_NONCE, err);
|
EXPECT_EQ(OEMCrypto_ERROR_INVALID_NONCE, err);
|
||||||
@@ -508,7 +627,7 @@ TEST(OdkTest, ParseLicenseErrorNonce) {
|
|||||||
|
|
||||||
TEST(OdkTest, ParseLicenseErrorUsageEntry) {
|
TEST(OdkTest, ParseLicenseErrorUsageEntry) {
|
||||||
ODK_LicenseResponseParams params;
|
ODK_LicenseResponseParams params;
|
||||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||||
uint8_t* buf = nullptr;
|
uint8_t* buf = nullptr;
|
||||||
uint32_t buf_size = 0;
|
uint32_t buf_size = 0;
|
||||||
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||||
@@ -516,25 +635,59 @@ TEST(OdkTest, ParseLicenseErrorUsageEntry) {
|
|||||||
params.usage_entry_present = false;
|
params.usage_entry_present = false;
|
||||||
OEMCryptoResult err = ODK_ParseLicense(
|
OEMCryptoResult err = ODK_ParseLicense(
|
||||||
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||||
params.usage_entry_present, params.request_hash, &(params.timer_limits),
|
params.usage_entry_present, &(params.timer_limits),
|
||||||
&(params.clock_values), &(params.core_message.nonce_values),
|
&(params.clock_values), &(params.core_message.nonce_values),
|
||||||
&(params.parsed_license));
|
&(params.parsed_license));
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OdkTest, ParseLicenseErrorRequestHash) {
|
TEST(OdkTest, ParseLicenseNullSubstring) {
|
||||||
ODK_LicenseResponseParams params;
|
ODK_LicenseResponseParams params;
|
||||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||||
|
params.parsed_license.srm_restriction_data.offset = 0;
|
||||||
|
params.parsed_license.srm_restriction_data.length = 0;
|
||||||
|
uint8_t* buf = nullptr;
|
||||||
|
uint32_t buf_size = 0;
|
||||||
|
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||||
|
&buf_size);
|
||||||
|
OEMCryptoResult result = ODK_ParseLicense(
|
||||||
|
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||||
|
params.usage_entry_present, &(params.timer_limits),
|
||||||
|
&(params.clock_values), &(params.core_message.nonce_values),
|
||||||
|
&(params.parsed_license));
|
||||||
|
EXPECT_EQ(OEMCrypto_SUCCESS, result);
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OdkTest, ParseLicenseErrorSubstringOffset) {
|
||||||
|
// offset out of range
|
||||||
|
ODK_LicenseResponseParams params;
|
||||||
|
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||||
|
params.parsed_license.enc_mac_keys_iv.offset = 1024;
|
||||||
uint8_t* buf = nullptr;
|
uint8_t* buf = nullptr;
|
||||||
uint32_t buf_size = 0;
|
uint32_t buf_size = 0;
|
||||||
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||||
&buf_size);
|
&buf_size);
|
||||||
// temporarily mess up with request hash
|
|
||||||
params.request_hash[0] = 0xff;
|
|
||||||
OEMCryptoResult err = ODK_ParseLicense(
|
OEMCryptoResult err = ODK_ParseLicense(
|
||||||
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||||
params.usage_entry_present, params.request_hash, &(params.timer_limits),
|
params.usage_entry_present, &(params.timer_limits),
|
||||||
|
&(params.clock_values), &(params.core_message.nonce_values),
|
||||||
|
&(params.parsed_license));
|
||||||
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
||||||
|
delete[] buf;
|
||||||
|
|
||||||
|
// offset + length out of range
|
||||||
|
err = OEMCrypto_SUCCESS;
|
||||||
|
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||||
|
params.parsed_license.enc_mac_keys_iv.length = buf_size;
|
||||||
|
buf = nullptr;
|
||||||
|
buf_size = 0;
|
||||||
|
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||||
|
&buf_size);
|
||||||
|
err = ODK_ParseLicense(
|
||||||
|
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||||
|
params.usage_entry_present, &(params.timer_limits),
|
||||||
&(params.clock_values), &(params.core_message.nonce_values),
|
&(params.clock_values), &(params.core_message.nonce_values),
|
||||||
&(params.parsed_license));
|
&(params.parsed_license));
|
||||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
||||||
@@ -582,21 +735,28 @@ class OdkVersionTest : public ::testing::Test,
|
|||||||
GetParam().response_major_version;
|
GetParam().response_major_version;
|
||||||
params->core_message.nonce_values.api_minor_version =
|
params->core_message.nonce_values.api_minor_version =
|
||||||
GetParam().response_minor_version;
|
GetParam().response_minor_version;
|
||||||
|
features_ =
|
||||||
|
CoreMessageFeatures::DefaultFeatures(GetParam().maximum_major_version);
|
||||||
}
|
}
|
||||||
|
CoreMessageFeatures features_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Serialize and de-serialize license response
|
// Serialize and de-serialize license response
|
||||||
TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
|
TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
|
||||||
ODK_LicenseResponseParams params;
|
ODK_LicenseResponseParams params;
|
||||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
ODK_SetDefaultLicenseResponseParams(¶ms,
|
||||||
|
GetParam().response_major_version);
|
||||||
SetRequestVersion(¶ms);
|
SetRequestVersion(¶ms);
|
||||||
// save a copy of params.request_hash as it will be zero out during the test
|
// For v17, we do not use the hash to verify the request. However, the server
|
||||||
|
// needs to be backwards compatible, so it still needs to pass the hash into
|
||||||
|
// CreateCoreLiceseseResponse below. Save a copy of params.request_hash as it
|
||||||
|
// will be zero out during the test
|
||||||
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
|
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
|
||||||
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
|
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
|
||||||
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
|
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
|
||||||
return ODK_ParseLicense(
|
return ODK_ParseLicense(
|
||||||
buf, size + kExtraPayloadSize, size, params.initial_license_load,
|
buf, size + kExtraPayloadSize, size, params.initial_license_load,
|
||||||
params.usage_entry_present, request_hash_read, &(params.timer_limits),
|
params.usage_entry_present, &(params.timer_limits),
|
||||||
&(params.clock_values), &(params.core_message.nonce_values),
|
&(params.clock_values), &(params.core_message.nonce_values),
|
||||||
&(params.parsed_license));
|
&(params.parsed_license));
|
||||||
};
|
};
|
||||||
@@ -605,8 +765,8 @@ TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
|
|||||||
sizeof(request_hash_read));
|
sizeof(request_hash_read));
|
||||||
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
|
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
return CreateCoreLicenseResponse(params.parsed_license, core_request,
|
return CreateCoreLicenseResponse(features_, params.parsed_license,
|
||||||
request_hash_string,
|
core_request, request_hash_string,
|
||||||
oemcrypto_core_message);
|
oemcrypto_core_message);
|
||||||
};
|
};
|
||||||
ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
|
ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
|
||||||
@@ -636,7 +796,7 @@ TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
|
|||||||
auto kdo_prepare_func = [&](ODK_RenewalRequest& core_request,
|
auto kdo_prepare_func = [&](ODK_RenewalRequest& core_request,
|
||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
core_request.playback_time_seconds = playback_clock;
|
core_request.playback_time_seconds = playback_clock;
|
||||||
return CreateCoreRenewalResponse(core_request, renewal_duration,
|
return CreateCoreRenewalResponse(features_, core_request, renewal_duration,
|
||||||
oemcrypto_core_message);
|
oemcrypto_core_message);
|
||||||
};
|
};
|
||||||
ValidateResponse<ODK_RenewalRequest>(GetParam(), &(params.core_message),
|
ValidateResponse<ODK_RenewalRequest>(GetParam(), &(params.core_message),
|
||||||
@@ -663,7 +823,7 @@ TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
|
|||||||
std::string* oemcrypto_core_message) {
|
std::string* oemcrypto_core_message) {
|
||||||
core_request.device_id.assign(reinterpret_cast<char*>(device_id),
|
core_request.device_id.assign(reinterpret_cast<char*>(device_id),
|
||||||
device_id_length);
|
device_id_length);
|
||||||
return CreateCoreProvisioningResponse(params.parsed_provisioning,
|
return CreateCoreProvisioningResponse(features_, params.parsed_provisioning,
|
||||||
core_request, oemcrypto_core_message);
|
core_request, oemcrypto_core_message);
|
||||||
};
|
};
|
||||||
ValidateResponse<ODK_ProvisioningRequest>(GetParam(), &(params.core_message),
|
ValidateResponse<ODK_ProvisioningRequest>(GetParam(), &(params.core_message),
|
||||||
@@ -687,26 +847,37 @@ const uint16_t kOldMajorMinor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION ? 42 : 0;
|
|||||||
// List of major and minor versions to test.
|
// List of major and minor versions to test.
|
||||||
std::vector<VersionParameters> TestCases() {
|
std::vector<VersionParameters> TestCases() {
|
||||||
std::vector<VersionParameters> test_cases{
|
std::vector<VersionParameters> test_cases{
|
||||||
// Fields: request major, request minor, response major, response minor
|
// Fields: maximum major version,
|
||||||
{ODK_MAJOR_VERSION, ODK_MINOR_VERSION, ODK_MAJOR_VERSION,
|
// request major, request minor, response major, response minor,
|
||||||
|
{ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, ODK_MINOR_VERSION,
|
||||||
|
ODK_MAJOR_VERSION, ODK_MINOR_VERSION},
|
||||||
|
{ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, ODK_MINOR_VERSION + 1,
|
||||||
|
ODK_MAJOR_VERSION, ODK_MINOR_VERSION},
|
||||||
|
{ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, kOldMinor, ODK_MAJOR_VERSION,
|
||||||
|
kOldMinor},
|
||||||
|
{ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, 0, ODK_MAJOR_VERSION, 0},
|
||||||
|
{ODK_MAJOR_VERSION, ODK_MAJOR_VERSION + 1, 42, ODK_MAJOR_VERSION,
|
||||||
ODK_MINOR_VERSION},
|
ODK_MINOR_VERSION},
|
||||||
{ODK_MAJOR_VERSION, ODK_MINOR_VERSION + 1, ODK_MAJOR_VERSION,
|
{ODK_MAJOR_VERSION, kOldMajor, 0, kOldMajor, 0},
|
||||||
ODK_MINOR_VERSION},
|
{ODK_MAJOR_VERSION, kOldMajor, kOldMajorMinor, kOldMajor, kOldMajorMinor},
|
||||||
{ODK_MAJOR_VERSION, kOldMinor, ODK_MAJOR_VERSION, kOldMinor},
|
// If the server is restricted to v16, then the response can be at
|
||||||
{ODK_MAJOR_VERSION, 0, ODK_MAJOR_VERSION, 0},
|
// most 16.5
|
||||||
{ODK_MAJOR_VERSION + 1, 42, ODK_MAJOR_VERSION, ODK_MINOR_VERSION},
|
{16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5},
|
||||||
{kOldMajor, 0, kOldMajor, 0},
|
|
||||||
{kOldMajor, kOldMajorMinor, kOldMajor, kOldMajorMinor},
|
|
||||||
// Here are some known good versions. Make extra sure they work.
|
// Here are some known good versions. Make extra sure they work.
|
||||||
{16, 3, 16, 3},
|
{16, 16, 3, 16, 3},
|
||||||
{16, 4, 16, 4},
|
{16, 16, 4, 16, 4},
|
||||||
{16, 5, 16, 5},
|
{16, 16, 5, 16, 5},
|
||||||
|
{17, 16, 3, 16, 3},
|
||||||
|
{17, 16, 4, 16, 4},
|
||||||
|
{17, 16, 5, 16, 5},
|
||||||
|
{17, 17, 0, 17, 0},
|
||||||
|
{17, 17, 1, 17, 1},
|
||||||
};
|
};
|
||||||
return test_cases;
|
return test_cases;
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(OdkVersionTests, OdkVersionTest,
|
INSTANTIATE_TEST_SUITE_P(OdkVersionTests, OdkVersionTest,
|
||||||
::testing::ValuesIn(TestCases()));
|
::testing::ValuesIn(TestCases()));
|
||||||
|
|
||||||
TEST(OdkSizeTest, LicenseRequest) {
|
TEST(OdkSizeTest, LicenseRequest) {
|
||||||
uint8_t* message = nullptr;
|
uint8_t* message = nullptr;
|
||||||
@@ -766,7 +937,7 @@ TEST(OdkSizeTest, ReleaseRequest) {
|
|||||||
&core_message_length, &nonce_values,
|
&core_message_length, &nonce_values,
|
||||||
&clock_values, system_time_seconds));
|
&clock_values, system_time_seconds));
|
||||||
// Release requests do not have a core message.
|
// Release requests do not have a core message.
|
||||||
EXPECT_GE(core_message_length, 0);
|
EXPECT_GE(core_message_length, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OdkSizeTest, ProvisioningRequest) {
|
TEST(OdkSizeTest, ProvisioningRequest) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
# Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
# source code may only be used and distributed under the Widevine Master License
|
# source code may only be used and distributed under the Widevine License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#include "odk_test_helper.h"
|
#include "odk_test_helper.h"
|
||||||
|
|
||||||
#include <endian.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "odk_endian.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
#include "odk_structs_priv.h"
|
#include "odk_structs_priv.h"
|
||||||
|
|
||||||
@@ -31,7 +31,8 @@ void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
|||||||
core_message->nonce_values.session_id = 0xcafebabe;
|
core_message->nonce_values.session_id = 0xcafebabe;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params) {
|
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
|
||||||
|
uint32_t odk_major_version) {
|
||||||
ODK_SetDefaultCoreFields(&(params->core_message), ODK_License_Response_Type);
|
ODK_SetDefaultCoreFields(&(params->core_message), ODK_License_Response_Type);
|
||||||
params->initial_license_load = true;
|
params->initial_license_load = true;
|
||||||
params->usage_entry_present = true;
|
params->usage_entry_present = true;
|
||||||
@@ -51,6 +52,29 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params) {
|
|||||||
.total_playback_duration_seconds = 12,
|
.total_playback_duration_seconds = 12,
|
||||||
.initial_renewal_duration_seconds = 13,
|
.initial_renewal_duration_seconds = 13,
|
||||||
},
|
},
|
||||||
|
.watermarking = 0,
|
||||||
|
.dtcp2_required = {.dtcp2_required = 0,
|
||||||
|
.cmi_descriptor_0 =
|
||||||
|
{
|
||||||
|
.id = 0,
|
||||||
|
.extension = 0,
|
||||||
|
.length = 1,
|
||||||
|
.data = 0,
|
||||||
|
},
|
||||||
|
.cmi_descriptor_1 =
|
||||||
|
{
|
||||||
|
.id = 1,
|
||||||
|
.extension = 0,
|
||||||
|
.length = 3,
|
||||||
|
.data = {0, 0, 0},
|
||||||
|
},
|
||||||
|
.cmi_descriptor_2 =
|
||||||
|
{
|
||||||
|
.id = 2,
|
||||||
|
.extension = 0,
|
||||||
|
.length = 3,
|
||||||
|
.data = {0, 0, 0},
|
||||||
|
}},
|
||||||
.key_array_length = 3,
|
.key_array_length = 3,
|
||||||
.key_array =
|
.key_array =
|
||||||
{
|
{
|
||||||
@@ -87,10 +111,10 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params) {
|
|||||||
".srm_restriction_data"},
|
".srm_restriction_data"},
|
||||||
{ODK_UINT32, &(params->parsed_license.license_type), ".license_type"},
|
{ODK_UINT32, &(params->parsed_license.license_type), ".license_type"},
|
||||||
{ODK_UINT32, &(params->parsed_license.nonce_required), ".nonce_required"},
|
{ODK_UINT32, &(params->parsed_license.nonce_required), ".nonce_required"},
|
||||||
{ODK_UINT32,
|
{ODK_BOOL,
|
||||||
&(params->parsed_license.timer_limits.soft_enforce_rental_duration),
|
&(params->parsed_license.timer_limits.soft_enforce_rental_duration),
|
||||||
".soft_enforce_rental_duration"},
|
".soft_enforce_rental_duration"},
|
||||||
{ODK_UINT32,
|
{ODK_BOOL,
|
||||||
&(params->parsed_license.timer_limits.soft_enforce_playback_duration),
|
&(params->parsed_license.timer_limits.soft_enforce_playback_duration),
|
||||||
".soft_enforce_playback_duration"},
|
".soft_enforce_playback_duration"},
|
||||||
{ODK_UINT64,
|
{ODK_UINT64,
|
||||||
@@ -105,37 +129,132 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params) {
|
|||||||
{ODK_UINT64,
|
{ODK_UINT64,
|
||||||
&(params->parsed_license.timer_limits.initial_renewal_duration_seconds),
|
&(params->parsed_license.timer_limits.initial_renewal_duration_seconds),
|
||||||
".initial_renewal_duration_seconds"},
|
".initial_renewal_duration_seconds"},
|
||||||
{ODK_UINT32, &(params->parsed_license.key_array_length),
|
|
||||||
".key_array_length"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_id), ".key_id"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_data_iv),
|
|
||||||
".key_data_iv"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_data),
|
|
||||||
".key_data"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_control_iv),
|
|
||||||
".key_control_iv"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_control),
|
|
||||||
".key_control"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_id), ".key_id"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_data_iv),
|
|
||||||
".key_data_iv"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_data),
|
|
||||||
".key_data"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_control_iv),
|
|
||||||
".key_control_iv"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_control),
|
|
||||||
".key_control"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_id), ".key_id"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_data_iv),
|
|
||||||
".key_data_iv"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_data),
|
|
||||||
".key_data"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_control_iv),
|
|
||||||
".key_control_iv"},
|
|
||||||
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_control),
|
|
||||||
".key_control"},
|
|
||||||
{ODK_HASH, params->request_hash, ".request_hash"},
|
|
||||||
};
|
};
|
||||||
|
if (odk_major_version >= 17) {
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT32, &(params->parsed_license.watermarking), ".watermarking"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8, &(params->parsed_license.dtcp2_required.dtcp2_required),
|
||||||
|
".dtcp2_required"});
|
||||||
|
if (params->parsed_license.dtcp2_required.dtcp2_required) {
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_0.id),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_0.extension),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT16,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_0.length),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_0.data),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_1.id),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_1.extension),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT16,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_1.length),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_1.data[0]),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_1.data[1]),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_1.data[2]),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_2.id),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_2.extension),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT16,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_2.length),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_2.data[0]),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_2.data[1]),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_UINT8,
|
||||||
|
&(params->parsed_license.dtcp2_required.cmi_descriptor_2.data[2]),
|
||||||
|
".cmi_descriptor_data"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params->extra_fields.push_back({ODK_UINT32,
|
||||||
|
&(params->parsed_license.key_array_length),
|
||||||
|
".key_array_length"});
|
||||||
|
params->extra_fields.push_back({ODK_SUBSTRING,
|
||||||
|
&(params->parsed_license.key_array[0].key_id),
|
||||||
|
".key_id"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_data_iv),
|
||||||
|
".key_data_iv"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_data),
|
||||||
|
".key_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_control_iv),
|
||||||
|
".key_control_iv"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[0].key_control),
|
||||||
|
".key_control"});
|
||||||
|
params->extra_fields.push_back({ODK_SUBSTRING,
|
||||||
|
&(params->parsed_license.key_array[1].key_id),
|
||||||
|
".key_id"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_data_iv),
|
||||||
|
".key_data_iv"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_data),
|
||||||
|
".key_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_control_iv),
|
||||||
|
".key_control_iv"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[1].key_control),
|
||||||
|
".key_control"});
|
||||||
|
params->extra_fields.push_back({ODK_SUBSTRING,
|
||||||
|
&(params->parsed_license.key_array[2].key_id),
|
||||||
|
".key_id"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_data_iv),
|
||||||
|
".key_data_iv"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_data),
|
||||||
|
".key_data"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_control_iv),
|
||||||
|
".key_control_iv"});
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_SUBSTRING, &(params->parsed_license.key_array[2].key_control),
|
||||||
|
".key_control"});
|
||||||
|
if (odk_major_version == 16) {
|
||||||
|
params->extra_fields.push_back(
|
||||||
|
{ODK_HASH, params->request_hash, ".request_hash"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) {
|
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) {
|
||||||
@@ -157,7 +276,7 @@ void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) {
|
|||||||
.initial_renewal_duration_seconds = 300,
|
.initial_renewal_duration_seconds = 300,
|
||||||
};
|
};
|
||||||
params->clock_values = {
|
params->clock_values = {
|
||||||
.time_of_license_signed =
|
.time_of_license_request_signed =
|
||||||
params->system_time - params->playback_clock - 42,
|
params->system_time - params->playback_clock - 42,
|
||||||
.time_of_first_decrypt = params->system_time - params->playback_clock,
|
.time_of_first_decrypt = params->system_time - params->playback_clock,
|
||||||
.time_of_last_decrypt = params->system_time - params->playback_clock,
|
.time_of_last_decrypt = params->system_time - params->playback_clock,
|
||||||
@@ -177,6 +296,7 @@ void ODK_SetDefaultProvisioningResponseParams(
|
|||||||
memset(params->device_id + params->device_id_length, 0,
|
memset(params->device_id + params->device_id_length, 0,
|
||||||
ODK_DEVICE_ID_LEN_MAX - params->device_id_length);
|
ODK_DEVICE_ID_LEN_MAX - params->device_id_length);
|
||||||
params->parsed_provisioning = {
|
params->parsed_provisioning = {
|
||||||
|
.key_type = OEMCrypto_RSA_Private_Key,
|
||||||
.enc_private_key = {.offset = 0, .length = 1},
|
.enc_private_key = {.offset = 0, .length = 1},
|
||||||
.enc_private_key_iv = {.offset = 2, .length = 3},
|
.enc_private_key_iv = {.offset = 2, .length = 3},
|
||||||
.encrypted_message_key = {.offset = 4, .length = 5},
|
.encrypted_message_key = {.offset = 4, .length = 5},
|
||||||
@@ -196,16 +316,22 @@ void ODK_SetDefaultProvisioningResponseParams(
|
|||||||
|
|
||||||
size_t ODK_FieldLength(ODK_FieldType type) {
|
size_t ODK_FieldLength(ODK_FieldType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case ODK_UINT8:
|
||||||
|
return sizeof(uint8_t);
|
||||||
case ODK_UINT16:
|
case ODK_UINT16:
|
||||||
return sizeof(uint16_t);
|
return sizeof(uint16_t);
|
||||||
case ODK_UINT32:
|
case ODK_UINT32:
|
||||||
return sizeof(uint32_t);
|
return sizeof(uint32_t);
|
||||||
case ODK_UINT64:
|
case ODK_UINT64:
|
||||||
return sizeof(uint64_t);
|
return sizeof(uint64_t);
|
||||||
|
case ODK_BOOL: // Booleans are stored in the message as 32 bit ints.
|
||||||
|
return sizeof(uint32_t);
|
||||||
case ODK_SUBSTRING:
|
case ODK_SUBSTRING:
|
||||||
return sizeof(uint32_t) + sizeof(uint32_t);
|
return sizeof(uint32_t) + sizeof(uint32_t);
|
||||||
case ODK_DEVICEID:
|
case ODK_DEVICEID:
|
||||||
return ODK_DEVICE_ID_LEN_MAX;
|
return ODK_DEVICE_ID_LEN_MAX;
|
||||||
|
case ODK_RENEWALDATA:
|
||||||
|
return ODK_KEYBOX_RENEWAL_DATA_SIZE;
|
||||||
case ODK_HASH:
|
case ODK_HASH:
|
||||||
return ODK_SHA256_HASH_SIZE;
|
return ODK_SHA256_HASH_SIZE;
|
||||||
default:
|
default:
|
||||||
@@ -225,30 +351,44 @@ OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field) {
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
|
case ODK_UINT8: {
|
||||||
|
memcpy(buf, field->value, sizeof(uint8_t));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ODK_UINT16: {
|
case ODK_UINT16: {
|
||||||
const uint16_t u16 = htobe16(*static_cast<uint16_t*>(field->value));
|
const uint16_t u16 =
|
||||||
|
oemcrypto_htobe16(*static_cast<uint16_t*>(field->value));
|
||||||
memcpy(buf, &u16, sizeof(u16));
|
memcpy(buf, &u16, sizeof(u16));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT32: {
|
case ODK_UINT32: {
|
||||||
const uint32_t u32 = htobe32(*static_cast<uint32_t*>(field->value));
|
const uint32_t u32 =
|
||||||
|
oemcrypto_htobe32(*static_cast<uint32_t*>(field->value));
|
||||||
memcpy(buf, &u32, sizeof(u32));
|
memcpy(buf, &u32, sizeof(u32));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT64: {
|
case ODK_UINT64: {
|
||||||
const uint64_t u64 = htobe64(*static_cast<uint64_t*>(field->value));
|
const uint64_t u64 =
|
||||||
|
oemcrypto_htobe64(*static_cast<uint64_t*>(field->value));
|
||||||
memcpy(buf, &u64, sizeof(u64));
|
memcpy(buf, &u64, sizeof(u64));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ODK_BOOL: {
|
||||||
|
const bool value = *static_cast<bool*>(field->value);
|
||||||
|
const uint32_t u32 = oemcrypto_htobe32(value ? 1 : 0);
|
||||||
|
memcpy(buf, &u32, sizeof(u32));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ODK_SUBSTRING: {
|
case ODK_SUBSTRING: {
|
||||||
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(field->value);
|
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(field->value);
|
||||||
const uint32_t off = htobe32(s->offset);
|
const uint32_t off = oemcrypto_htobe32(s->offset);
|
||||||
const uint32_t len = htobe32(s->length);
|
const uint32_t len = oemcrypto_htobe32(s->length);
|
||||||
memcpy(buf, &off, sizeof(off));
|
memcpy(buf, &off, sizeof(off));
|
||||||
memcpy(buf + sizeof(off), &len, sizeof(len));
|
memcpy(buf + sizeof(off), &len, sizeof(len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_DEVICEID:
|
case ODK_DEVICEID:
|
||||||
|
case ODK_RENEWALDATA:
|
||||||
case ODK_HASH: {
|
case ODK_HASH: {
|
||||||
const size_t field_len = ODK_FieldLength(field->type);
|
const size_t field_len = ODK_FieldLength(field->type);
|
||||||
const uint8_t* const id = static_cast<uint8_t*>(field->value);
|
const uint8_t* const id = static_cast<uint8_t*>(field->value);
|
||||||
@@ -268,22 +408,33 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
|
case ODK_UINT8: {
|
||||||
|
memcpy(field->value, buf, sizeof(uint8_t));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ODK_UINT16: {
|
case ODK_UINT16: {
|
||||||
memcpy(field->value, buf, sizeof(uint16_t));
|
memcpy(field->value, buf, sizeof(uint16_t));
|
||||||
uint16_t* u16p = static_cast<uint16_t*>(field->value);
|
uint16_t* u16p = static_cast<uint16_t*>(field->value);
|
||||||
*u16p = be16toh(*u16p);
|
*u16p = oemcrypto_be16toh(*u16p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT32: {
|
case ODK_UINT32: {
|
||||||
memcpy(field->value, buf, sizeof(uint32_t));
|
memcpy(field->value, buf, sizeof(uint32_t));
|
||||||
uint32_t* u32p = static_cast<uint32_t*>(field->value);
|
uint32_t* u32p = static_cast<uint32_t*>(field->value);
|
||||||
*u32p = be32toh(*u32p);
|
*u32p = oemcrypto_be32toh(*u32p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT64: {
|
case ODK_UINT64: {
|
||||||
memcpy(field->value, buf, sizeof(uint64_t));
|
memcpy(field->value, buf, sizeof(uint64_t));
|
||||||
uint64_t* u64p = static_cast<uint64_t*>(field->value);
|
uint64_t* u64p = static_cast<uint64_t*>(field->value);
|
||||||
*u64p = be64toh(*u64p);
|
*u64p = oemcrypto_be64toh(*u64p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ODK_BOOL: {
|
||||||
|
uint32_t value;
|
||||||
|
memcpy(&value, buf, sizeof(uint32_t));
|
||||||
|
value = oemcrypto_be32toh(value);
|
||||||
|
*static_cast<bool*>(field->value) = (value != 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_SUBSTRING: {
|
case ODK_SUBSTRING: {
|
||||||
@@ -292,11 +443,12 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
|
|||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
memcpy(&off, buf, sizeof(off));
|
memcpy(&off, buf, sizeof(off));
|
||||||
memcpy(&len, buf + sizeof(off), sizeof(len));
|
memcpy(&len, buf + sizeof(off), sizeof(len));
|
||||||
s->offset = be32toh(off);
|
s->offset = oemcrypto_be32toh(off);
|
||||||
s->length = be32toh(len);
|
s->length = oemcrypto_be32toh(len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_DEVICEID:
|
case ODK_DEVICEID:
|
||||||
|
case ODK_RENEWALDATA:
|
||||||
case ODK_HASH: {
|
case ODK_HASH: {
|
||||||
const size_t field_len = ODK_FieldLength(field->type);
|
const size_t field_len = ODK_FieldLength(field->type);
|
||||||
uint8_t* const id = static_cast<uint8_t*>(field->value);
|
uint8_t* const id = static_cast<uint8_t*>(field->value);
|
||||||
@@ -315,18 +467,26 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case ODK_UINT16: {
|
case ODK_UINT8: {
|
||||||
uint16_t val;
|
uint8_t val;
|
||||||
memcpy(&val, buf, sizeof(uint16_t));
|
memcpy(&val, buf, sizeof(uint8_t));
|
||||||
val = be16toh(val);
|
|
||||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
<< "\n";
|
<< "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ODK_UINT16: {
|
||||||
|
uint16_t val;
|
||||||
|
memcpy(&val, buf, sizeof(uint16_t));
|
||||||
|
val = oemcrypto_be16toh(val);
|
||||||
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
|
<< "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ODK_BOOL:
|
||||||
case ODK_UINT32: {
|
case ODK_UINT32: {
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
memcpy(&val, buf, sizeof(uint32_t));
|
memcpy(&val, buf, sizeof(uint32_t));
|
||||||
val = be32toh(val);
|
val = oemcrypto_be32toh(val);
|
||||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
<< "\n";
|
<< "\n";
|
||||||
break;
|
break;
|
||||||
@@ -334,7 +494,7 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
|||||||
case ODK_UINT64: {
|
case ODK_UINT64: {
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
memcpy(&val, buf, sizeof(uint64_t));
|
memcpy(&val, buf, sizeof(uint64_t));
|
||||||
val = be64toh(val);
|
val = oemcrypto_be64toh(val);
|
||||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
<< "\n";
|
<< "\n";
|
||||||
break;
|
break;
|
||||||
@@ -348,6 +508,7 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_DEVICEID:
|
case ODK_DEVICEID:
|
||||||
|
case ODK_RENEWALDATA:
|
||||||
case ODK_HASH: {
|
case ODK_HASH: {
|
||||||
const size_t field_len = ODK_FieldLength(field->type);
|
const size_t field_len = ODK_FieldLength(field->type);
|
||||||
std::cerr << field->name << ": ";
|
std::cerr << field->name << ": ";
|
||||||
@@ -447,7 +608,8 @@ void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
|
|||||||
std::fstream out(tmp, std::ios::out | std::ios::binary);
|
std::fstream out(tmp, std::ios::out | std::ios::binary);
|
||||||
out.write(static_cast<const char*>(buffers[i]), n);
|
out.write(static_cast<const char*>(buffers[i]), n);
|
||||||
out.close();
|
out.close();
|
||||||
std::cerr << "buffer " << i << " dumped to " << tmp << std::endl;
|
std::cerr << std::endl
|
||||||
|
<< "Message buffer " << i << " dumped to " << tmp << std::endl;
|
||||||
size_t bytes_written;
|
size_t bytes_written;
|
||||||
uint8_t* buf =
|
uint8_t* buf =
|
||||||
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffers[i]));
|
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffers[i]));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
// Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
// source code may only be used and distributed under the Widevine Master
|
// source code may only be used and distributed under the Widevine
|
||||||
// License Agreement.
|
// License Agreement.
|
||||||
|
|
||||||
#ifndef WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_
|
#ifndef WIDEVINE_ODK_TEST_ODK_TEST_HELPER_H_
|
||||||
@@ -15,13 +15,20 @@
|
|||||||
namespace wvodk_test {
|
namespace wvodk_test {
|
||||||
|
|
||||||
enum ODK_FieldType {
|
enum ODK_FieldType {
|
||||||
|
ODK_UINT8,
|
||||||
ODK_UINT16,
|
ODK_UINT16,
|
||||||
ODK_UINT32,
|
ODK_UINT32,
|
||||||
ODK_UINT64,
|
ODK_UINT64,
|
||||||
ODK_SUBSTRING,
|
ODK_SUBSTRING,
|
||||||
ODK_DEVICEID,
|
ODK_DEVICEID,
|
||||||
|
ODK_RENEWALDATA,
|
||||||
ODK_HASH,
|
ODK_HASH,
|
||||||
ODK_NUMTYPES,
|
// The "stressable" types are the ones we can put in a stress test that packs
|
||||||
|
// and unpacks random data and can expect to get back the same thing.
|
||||||
|
ODK_LAST_STRESSABLE_TYPE,
|
||||||
|
// Put boolean after ODK_LAST_STRESSABLE_TYPE, so that we skip boolean type in
|
||||||
|
// SerializeFieldsStress because we unpack any nonzero to 'true'.
|
||||||
|
ODK_BOOL,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ODK_FieldMode {
|
enum ODK_FieldMode {
|
||||||
@@ -36,6 +43,8 @@ struct ODK_Field {
|
|||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This structure contains all parameters available in message version v16
|
||||||
|
// through the current version.
|
||||||
struct ODK_LicenseResponseParams {
|
struct ODK_LicenseResponseParams {
|
||||||
ODK_CoreMessage core_message;
|
ODK_CoreMessage core_message;
|
||||||
bool initial_license_load;
|
bool initial_license_load;
|
||||||
@@ -69,7 +78,8 @@ struct ODK_ProvisioningResponseParams {
|
|||||||
// Default values in core_message for testing
|
// Default values in core_message for testing
|
||||||
void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
||||||
ODK_MessageType message_type);
|
ODK_MessageType message_type);
|
||||||
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params);
|
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
|
||||||
|
uint32_t odk_major_version);
|
||||||
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params);
|
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params);
|
||||||
void ODK_SetDefaultProvisioningResponseParams(
|
void ODK_SetDefaultProvisioningResponseParams(
|
||||||
ODK_ProvisioningResponseParams* params);
|
ODK_ProvisioningResponseParams* params);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
/* Copyright 2019 Google LLC. All rights reserved. This file and proprietary
|
||||||
* source code may only be used and distributed under the Widevine Master
|
* source code may only be used and distributed under the Widevine
|
||||||
* License Agreement.
|
* License Agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ TEST(OdkTimerBasicTest, Init) {
|
|||||||
memset(&clock_values, 0, sizeof(clock_values));
|
memset(&clock_values, 0, sizeof(clock_values));
|
||||||
uint64_t time = 42;
|
uint64_t time = 42;
|
||||||
ODK_InitializeClockValues(&clock_values, time);
|
ODK_InitializeClockValues(&clock_values, time);
|
||||||
EXPECT_EQ(clock_values.time_of_license_signed, time);
|
EXPECT_EQ(clock_values.time_of_license_request_signed, time);
|
||||||
EXPECT_EQ(clock_values.time_of_first_decrypt, 0u);
|
EXPECT_EQ(clock_values.time_of_first_decrypt, 0u);
|
||||||
EXPECT_EQ(clock_values.time_of_last_decrypt, 0u);
|
EXPECT_EQ(clock_values.time_of_last_decrypt, 0u);
|
||||||
EXPECT_EQ(clock_values.time_when_timer_expires, 0u);
|
EXPECT_EQ(clock_values.time_when_timer_expires, 0u);
|
||||||
@@ -59,7 +59,7 @@ TEST(OdkTimerBasicTest, Reload) {
|
|||||||
enum OEMCrypto_Usage_Entry_Status status = kInactiveUsed;
|
enum OEMCrypto_Usage_Entry_Status status = kInactiveUsed;
|
||||||
ODK_ReloadClockValues(&clock_values, lic_signed, first_decrypt, last_decrypt,
|
ODK_ReloadClockValues(&clock_values, lic_signed, first_decrypt, last_decrypt,
|
||||||
status, time);
|
status, time);
|
||||||
EXPECT_EQ(clock_values.time_of_license_signed, lic_signed);
|
EXPECT_EQ(clock_values.time_of_license_request_signed, lic_signed);
|
||||||
EXPECT_EQ(clock_values.time_of_first_decrypt, first_decrypt);
|
EXPECT_EQ(clock_values.time_of_first_decrypt, first_decrypt);
|
||||||
EXPECT_EQ(clock_values.time_of_last_decrypt, last_decrypt);
|
EXPECT_EQ(clock_values.time_of_last_decrypt, last_decrypt);
|
||||||
EXPECT_EQ(clock_values.time_when_timer_expires, 0u);
|
EXPECT_EQ(clock_values.time_when_timer_expires, 0u);
|
||||||
@@ -95,7 +95,7 @@ class ODKTimerTest : public ::testing::Test {
|
|||||||
// Start rental clock at kRentalClockStart. This happens when the license
|
// Start rental clock at kRentalClockStart. This happens when the license
|
||||||
// request is signed.
|
// request is signed.
|
||||||
ODK_InitializeClockValues(&clock_values_, kRentalClockStart);
|
ODK_InitializeClockValues(&clock_values_, kRentalClockStart);
|
||||||
EXPECT_EQ(clock_values_.time_of_license_signed, kRentalClockStart);
|
EXPECT_EQ(clock_values_.time_of_license_request_signed, kRentalClockStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate loading or reloading a license in a new session. An offline
|
// Simulate loading or reloading a license in a new session. An offline
|
||||||
@@ -113,14 +113,14 @@ class ODKTimerTest : public ::testing::Test {
|
|||||||
ODK_InitializeClockValues(&clock_values_, 0);
|
ODK_InitializeClockValues(&clock_values_, 0);
|
||||||
// When the usage entry is reloaded, the clock values are reloaded.
|
// When the usage entry is reloaded, the clock values are reloaded.
|
||||||
ODK_ReloadClockValues(&clock_values_,
|
ODK_ReloadClockValues(&clock_values_,
|
||||||
old_clock_values.time_of_license_signed,
|
old_clock_values.time_of_license_request_signed,
|
||||||
old_clock_values.time_of_first_decrypt,
|
old_clock_values.time_of_first_decrypt,
|
||||||
old_clock_values.time_of_last_decrypt,
|
old_clock_values.time_of_last_decrypt,
|
||||||
old_clock_values.status, system_time);
|
old_clock_values.status, system_time);
|
||||||
EXPECT_EQ(clock_values_.timer_status,
|
EXPECT_EQ(clock_values_.timer_status,
|
||||||
ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED);
|
ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED);
|
||||||
// These shall not change:
|
// These shall not change:
|
||||||
EXPECT_EQ(clock_values_.time_of_license_signed, kRentalClockStart);
|
EXPECT_EQ(clock_values_.time_of_license_request_signed, kRentalClockStart);
|
||||||
EXPECT_EQ(clock_values_.time_of_first_decrypt,
|
EXPECT_EQ(clock_values_.time_of_first_decrypt,
|
||||||
old_clock_values.time_of_first_decrypt);
|
old_clock_values.time_of_first_decrypt);
|
||||||
EXPECT_EQ(clock_values_.time_of_last_decrypt,
|
EXPECT_EQ(clock_values_.time_of_last_decrypt,
|
||||||
@@ -215,8 +215,8 @@ class ODKTimerTest : public ::testing::Test {
|
|||||||
ODK_TIMER_EXPIRED);
|
ODK_TIMER_EXPIRED);
|
||||||
// These should not have changed. In particular, if the license was unused
|
// These should not have changed. In particular, if the license was unused
|
||||||
// before, it should reamin unused.
|
// before, it should reamin unused.
|
||||||
EXPECT_EQ(clock_values_.time_of_license_signed,
|
EXPECT_EQ(clock_values_.time_of_license_request_signed,
|
||||||
old_clock_values.time_of_license_signed);
|
old_clock_values.time_of_license_request_signed);
|
||||||
EXPECT_EQ(clock_values_.time_of_first_decrypt,
|
EXPECT_EQ(clock_values_.time_of_first_decrypt,
|
||||||
old_clock_values.time_of_first_decrypt);
|
old_clock_values.time_of_first_decrypt);
|
||||||
EXPECT_EQ(clock_values_.time_of_last_decrypt,
|
EXPECT_EQ(clock_values_.time_of_last_decrypt,
|
||||||
@@ -226,7 +226,7 @@ class ODKTimerTest : public ::testing::Test {
|
|||||||
|
|
||||||
// Verify that the clock values are correct.
|
// Verify that the clock values are correct.
|
||||||
void CheckClockValues(uint64_t time_of_last_decrypt) {
|
void CheckClockValues(uint64_t time_of_last_decrypt) {
|
||||||
EXPECT_EQ(clock_values_.time_of_license_signed, kRentalClockStart);
|
EXPECT_EQ(clock_values_.time_of_license_request_signed, kRentalClockStart);
|
||||||
EXPECT_EQ(clock_values_.time_of_first_decrypt, start_of_playback_);
|
EXPECT_EQ(clock_values_.time_of_first_decrypt, start_of_playback_);
|
||||||
EXPECT_EQ(clock_values_.time_of_last_decrypt, time_of_last_decrypt);
|
EXPECT_EQ(clock_values_.time_of_last_decrypt, time_of_last_decrypt);
|
||||||
EXPECT_EQ(clock_values_.status, kActive);
|
EXPECT_EQ(clock_values_.status, kActive);
|
||||||
@@ -1133,8 +1133,8 @@ TEST_P(ODKUseCase_LicenseWithRenewal, NullPointerTest) {
|
|||||||
timer_value_pointer);
|
timer_value_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(RestrictRenewal, ODKUseCase_LicenseWithRenewal,
|
INSTANTIATE_TEST_SUITE_P(RestrictRenewal, ODKUseCase_LicenseWithRenewal,
|
||||||
::testing::Values(0, 1));
|
::testing::Values(0, 1));
|
||||||
|
|
||||||
// Limited Duration License. (See above for notes on Use Case tests). The user
|
// Limited Duration License. (See above for notes on Use Case tests). The user
|
||||||
// has 15 minutes to begin watching the movie. If a renewal is not received,
|
// has 15 minutes to begin watching the movie. If a renewal is not received,
|
||||||
|
|||||||
Reference in New Issue
Block a user