diff --git a/oemcrypto/Android.bp b/oemcrypto/Android.bp
new file mode 100644
index 0000000..3416917
--- /dev/null
+++ b/oemcrypto/Android.bp
@@ -0,0 +1,145 @@
+// Copyright 2024 Google LLC. This file and proprietary
+// source code may only be used and distributed under the Widevine
+// License Agreement.
+
+package {
+ default_applicable_licenses: ["vendor_widevine_license"],
+}
+
+// Header Library for public OEMCrypto API.
+cc_library_headers {
+ name: "oemcrypto_api_headers",
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ owner: "widevine",
+ min_sdk_version: "34",
+}
+
+cc_defaults {
+ name: "oemcrypto_test_defaults",
+ team: "trendy_team_media_framework_drm",
+
+ // The unit tests can access v15 functions through the dynamic adapter:
+ cflags: ["-DTEST_OEMCRYPTO_V15"],
+
+ srcs: [
+ "test/GEN_api_lock_file.c",
+ "test/oec_device_features.cpp",
+ "test/oec_decrypt_fallback_chain.cpp",
+ "test/oec_key_deriver.cpp",
+ "test/oec_session_util.cpp",
+ "test/oemcrypto_corpus_generator_helper.cpp",
+ "test/oemcrypto_session_tests_helper.cpp",
+ "test/oemcrypto_basic_test.cpp",
+ "test/oemcrypto_cast_test.cpp",
+ "test/oemcrypto_decrypt_test.cpp",
+ "test/oemcrypto_generic_crypto_test.cpp",
+ "test/oemcrypto_license_test.cpp",
+ "test/oemcrypto_provisioning_test.cpp",
+ "test/oemcrypto_security_test.cpp",
+ "test/oemcrypto_usage_table_test.cpp",
+ "test/oemcrypto_test.cpp",
+ "test/oemcrypto_test_android.cpp",
+ "test/oemcrypto_test_main.cpp",
+ "test/ota_keybox_test.cpp",
+ "util/src/bcc_validator.cpp",
+ "util/src/cbor_validator.cpp",
+ "util/src/cose_utils.cpp",
+ "util/src/device_info_validator.cpp",
+ "util/src/oemcrypto_cose_key.cpp",
+ "util/src/oemcrypto_ecc_key.cpp",
+ "util/src/oemcrypto_ed_key.cpp",
+ "util/src/oemcrypto_rsa_key.cpp",
+ "util/src/prov4_validation_helper.cpp",
+ "util/src/signed_csr_payload_validator.cpp",
+ "util/src/wvcrc32.cpp",
+ ":cdm_test_sleep",
+ ],
+
+ include_dirs: [
+ "external/googletest/googlemock/include",
+ "vendor/widevine/libwvdrmengine/cdm/core/include",
+ "vendor/widevine/libwvdrmengine/cdm/util/include",
+ "vendor/widevine/libwvdrmengine/cdm/util/test",
+ ],
+ local_include_dirs: [
+ "test/fuzz_tests",
+ "include",
+ "odk/include",
+ "util/include",
+ ],
+
+ static_libs: [
+ "libcppbor",
+ "libjsmn",
+ "libgmock",
+ "libgtest",
+ "libgtest_main",
+ "libPlatformProperties",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcrypto",
+ "libdl",
+ "libbinder_ndk",
+ "liblog",
+ "libmedia_omx",
+ "libprotobuf-cpp-lite",
+ "libstagefright_foundation",
+ "libutils",
+ "libz",
+ ],
+}
+
+cc_defaults {
+ name: "oemcrypto_test_defaults_vendor",
+ static_libs: [
+ "libcdm",
+ "libcdm_protos",
+ "libcdm_utils",
+ "libwv_odk",
+ "libwv_kdo",
+ "libwvlevel3",
+ ],
+}
+
+cc_defaults {
+ name: "oemcrypto_test_defaults_system",
+ static_libs: [
+ "libcdm.system",
+ "libcdm_protos.system",
+ "libcdm_utils.system",
+ "libwv_odk.system",
+ "libwv_kdo.system",
+ "libwvlevel3.system",
+ ],
+}
+
+cc_test {
+ name: "oemcrypto_test",
+ team: "trendy_team_media_framework_drm",
+ owner: "widevine",
+ defaults: [
+ "oemcrypto_test_defaults",
+ "oemcrypto_test_defaults_vendor",
+ ],
+ proprietary: true,
+}
+
+cc_test {
+ name: "oemcrypto_test.system",
+ team: "trendy_team_media_framework_drm",
+ owner: "widevine",
+ defaults: [
+ "oemcrypto_test_defaults",
+ "oemcrypto_test_defaults_system",
+ ],
+ test_config_template: "AndroidTest.xml",
+ test_suites: [
+ "general-tests",
+ ],
+}
diff --git a/oemcrypto/AndroidTest.xml b/oemcrypto/AndroidTest.xml
new file mode 100644
index 0000000..4d1ff2b
--- /dev/null
+++ b/oemcrypto/AndroidTest.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/oemcrypto/include/OEMCryptoCENC.h b/oemcrypto/include/OEMCryptoCENC.h
index f2cf389..fc4fc2e 100644
--- a/oemcrypto/include/OEMCryptoCENC.h
+++ b/oemcrypto/include/OEMCryptoCENC.h
@@ -3,7 +3,7 @@
// License Agreement.
/**
- * @mainpage OEMCrypto API v19.5
+ * @mainpage OEMCrypto API v20.0
*
* OEMCrypto is the low level library implemented by the OEM to provide key and
* content protection, usually in a separate secure memory or process space. The
@@ -444,7 +444,7 @@ typedef struct {
*/
typedef struct {
uint8_t signature[20]; // -- HMAC SHA1 of the rest of the report.
- uint8_t status; // current status of entry. (OEMCrypto_Usage_Entry_Status)
+ uint8_t status; // current status of entry. (OEMCrypto_UsageEntryStatus)
uint8_t clock_security_level;
uint8_t pst_length;
uint8_t padding; // make int64's word aligned.
@@ -455,17 +455,6 @@ typedef struct {
} __attribute__((packed)) OEMCrypto_PST_Report;
#endif
-/**
- * Valid values for clock_security_level in OEMCrypto_PST_Report.
- */
-typedef enum OEMCrypto_Clock_Security_Level {
- kInsecureClock = 0,
- kMonotonicClock = 1,
- kSecureTimer = 1, // DEPRECATED. Do not use.
- kSecureClock = 2,
- kHardwareSecureClock = 3
-} OEMCrypto_Clock_Security_Level;
-
typedef uint8_t RSA_Padding_Scheme;
// RSASSA-PSS with SHA1. Scheme used for DRM certificates for signing a license
// request.
@@ -766,6 +755,8 @@ typedef enum OEMCrypto_SignatureHashAlgorithm {
#define OEMCrypto_GetBCCSignatureType _oecc156
#define OEMCrypto_GetPVRKey _oecc157
#define OEMCrypto_LoadPVRKey _oecc158
+#define OEMCrypto_LoadLicenseData _oecc159
+#define OEMCrypto_SaveLicenseData _oecc160
// clang-format on
/// @addtogroup initcontrol
@@ -1027,7 +1018,10 @@ OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session);
* state, an error of OEMCrypto_ERROR_INVALID_CONTEXT is returned.
*
* @param[in] session: handle for the session to be used.
- * @param[out] nonce: pointer to memory to receive the computed nonce.
+ * @param[out] nonce pointer to memory to receive the computed nonce. The nonce
+ * will only be stored into this memory location if the function returns
+ * OEMCrypto_SUCCESS. If any other OEMCryptoResult is returned, the contents
+ * of the memory pointed to by nonce will remain unchanged.
*
* Results:
* nonce: the nonce is also stored in secure memory.
@@ -1192,14 +1186,12 @@ OEMCryptoResult OEMCrypto_PrepAndSignLicenseRequest(
* larger than the supported size.
*
* @threading
- * This is a "Session Function" and may be called simultaneously with session
- * functions for other sessions but not simultaneously with other functions
- * for this session. It will not be called simultaneously with initialization
- * or usage table functions. It is as if the CDM holds a write lock for this
- * session, and a read lock on the OEMCrypto system.
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
*
* @version
- * This method is new in API version 19.
+ * This method is new in API version 20.
*/
OEMCryptoResult OEMCrypto_PrepAndSignReleaseRequest(
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
@@ -1319,12 +1311,12 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
* mac_keys may be deleted.
*
* If the field license_type is OEMCrypto_ContentLicense, then the fields
- * key_id and key_data in an OEMCrypto_KeyObject are loaded in to the
+ * key_id and key_data in an OEMCrypto_KeyObjectV2 are loaded in to the
* content_key_id and content_key_data fields of the key table entry. In this
* case, entitlement key ids and entitlement key data is left blank.
*
* If the field license_type is OEMCrypto_EntitlementLicense, then the
- * fields key_id and key_data in an OEMCrypto_KeyObject are loaded in to the
+ * fields key_id and key_data in an OEMCrypto_KeyObjectV2 are loaded in to the
* entitlement_key_id and entitlement_key_data fields of the key table entry.
* In this case, content key ids and content key data will be loaded later
* with a call to OEMCrypto_LoadEntitledContentKeys().
@@ -1381,8 +1373,8 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
* 22. If key_array_length == 0, then return
* OEMCrypto_ERROR_INVALID_CONTEXT.
* 23. If this session is associated with a usage table entry, and that
- * entry is marked as "inactive" (either kInactiveUsed or
- * kInactiveUnused), then the keys are not loaded, and the error
+ * entry is marked as "inactive" (either OEMCrypto_InactiveUsed or
+ * OEMCrypto_InactiveUnused), then the keys are not loaded, and the error
* OEMCrypto_ERROR_LICENSE_INACTIVE is returned.
* 24. The data in enc_mac_keys_iv is not identical to the 16 bytes before
* enc_mac_keys. If it is, return OEMCrypto_ERROR_INVALID_CONTEXT.
@@ -1643,14 +1635,12 @@ OEMCryptoResult OEMCrypto_LoadRenewal(OEMCrypto_SESSION session,
* @retval OEMCrypto_ERROR_SIGNATURE_FAILURE
*
* @threading
- * This is a "Session Function" and may be called simultaneously with session
- * functions for other sessions but not simultaneously with other functions
- * for this session. It will not be called simultaneously with initialization
- * or usage table functions. It is as if the CDM holds a write lock for this
- * session, and a read lock on the OEMCrypto system.
+ * This is a "Usage Table Function" and will not be called simultaneously
+ * with any other function, as if the CDM holds a write lock on the OEMCrypto
+ * system.
*
* @version
- * This method is new in API version 19.
+ * This method is new in API version 20.
*/
OEMCryptoResult OEMCrypto_LoadRelease(OEMCrypto_SESSION session,
const uint8_t* message,
@@ -2491,8 +2481,8 @@ OEMCryptoResult OEMCrypto_GetKeyHandle(OEMCrypto_SESSION session,
* OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION. (See note on delayed
* error conditions below)
* 5. If the current key has an entry in the Usage Table, and the status of
- * that entry is either kInactiveUsed or kInactiveUnused, then return the
- * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ * that entry is either OEMCrypto_InactiveUsed or OEMCrypto_InactiveUnused,
+ * then return the error OEMCrypto_ERROR_LICENSE_INACTIVE.
* 6. If a Decrypt Hash has been initialized via OEMCrypto_SetDecryptHash(),
* and the current key's control block does not have the
* Allow_Hash_Verification bit set, then do not compute a hash and
@@ -2732,8 +2722,8 @@ OEMCryptoResult OEMCrypto_CopyBuffer(
* 1. The control bit for the key shall have the Allow_Encrypt set. If not,
* return OEMCrypto_ERROR_UNKNOWN_FAILURE.
* 2. If the key has an entry in the Usage Table, and the status of that
- * entry is either kInactiveUsed or kInactiveUnused, then return the
- * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ * entry is either OEMCrypto_InactiveUsed or OEMCrypto_InactiveUnused,
+ * then return the error OEMCrypto_ERROR_LICENSE_INACTIVE.
*
* @param[in] key_handle: pointer to a buffer containing the key handle for a
* key previously installed with OEMCrypto_GetKeyHandle().
@@ -2816,8 +2806,8 @@ OEMCryptoResult OEMCrypto_Generic_Encrypt(
* 2. If the key's control block has the Data_Path_Type bit set, then return
* OEMCrypto_ERROR_DECRYPT_FAILED.
* 3. If the key has an entry in the Usage Table, and the status of that
- * entry is either kInactiveUsed or kInactiveUnused, then return the
- * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ * entry is either OEMCrypto_InactiveUsed or OEMCrypto_InactiveUnused,
+ * then return the error OEMCrypto_ERROR_LICENSE_INACTIVE.
*
* @param[in] key_handle: pointer to a buffer containing the key handle for a
* key previously installed with OEMCrypto_GetKeyHandle().
@@ -2896,8 +2886,8 @@ OEMCryptoResult OEMCrypto_Generic_Decrypt(
* returned, and the data is not signed.
* 1. The control bit for the key shall have the Allow_Sign set.
* 2. If the key has an entry in the Usage Table, and the status of that
- * entry is either kInactiveUsed or kInactiveUnused, then return the
- * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ * entry is either OEMCrypto_InactiveUsed or OEMCrypto_InactiveUnused,
+ * then return the error OEMCrypto_ERROR_LICENSE_INACTIVE.
*
* @param[in] key_handle: pointer to a buffer containing the key handle for a
* key previously installed with OEMCrypto_GetKeyHandle().
@@ -2986,8 +2976,8 @@ OEMCryptoResult OEMCrypto_Generic_Sign(const uint8_t* key_handle,
* signature mismatch will always take the same time as a successful
* comparison).
* 4. If the key has an entry in the Usage Table, and the status of that
- * entry is either kInactiveUsed or kInactiveUnused, then return the
- * error OEMCrypto_ERROR_LICENSE_INACTIVE.
+ * entry is either OEMCrypto_InactiveUsed or OEMCrypto_InactiveUnused,
+ * then return the error OEMCrypto_ERROR_LICENSE_INACTIVE.
*
* @param[in] key_handle: pointer to a buffer containing the key handle for a
* key previously installed with OEMCrypto_GetKeyHandle().
@@ -4314,8 +4304,8 @@ OEMCryptoResult OEMCrypto_LoadProvisioning(
* Receiver certificates may refuse to load these keys and return an error of
* OEMCrypto_ERROR_NOT_IMPLEMENTED. The main use case for these alternative
* signing algorithms is to support devices that use X509 certificates for
- * authentication when acting as a ChromeCast receiver. This is not needed for
- * devices that wish to send data to a ChromeCast. Keys loaded from this
+ * authentication when acting as a Google Cast receiver. This is not needed for
+ * devices that wish to send data to a Google Cast. Keys loaded from this
* function may not be used with OEMCrypto_PrepAndSignLicenseRequest().
*
* First, OEMCrypto should generate three secondary keys, mac_key[server],
@@ -4388,8 +4378,8 @@ OEMCryptoResult OEMCrypto_LoadProvisioning(
* algorithms may refuse to load these keys and return an error of
* OEMCrypto_ERROR_NOT_IMPLEMENTED. The main use case for these
* alternative signing algorithms is to support devices that use X.509
- * certificates for authentication when acting as a ChromeCast receiver.
- * This is not needed for devices that wish to send data to a ChromeCast.
+ * certificates for authentication when acting as a Google Cast receiver.
+ * This is not needed for devices that wish to send data to a Google Cast.
* 7. After possibly skipping past the first 8 bytes signifying the allowed
* signing algorithm, the rest of the buffer private_key contains an ECC
* private key or an RSA private key in PKCS#8 binary DER encoded
@@ -4562,7 +4552,7 @@ OEMCryptoResult OEMCrypto_LoadTestRSAKey(void);
*
* The second padding scheme is for devices that use X509 certificates for
* authentication. The main example is devices that work as a Cast receiver,
- * like a ChromeCast, not for devices that wish to send to the Cast device,
+ * like a Google Cast, not for devices that wish to send to the Cast device,
* such as almost all Android devices. OEMs that do not support X509
* certificate authentication need not implement this function and can return
* OEMCrypto_ERROR_NOT_IMPLEMENTED.
@@ -4703,8 +4693,8 @@ OEMCryptoResult OEMCrypto_PrepAndSignProvisioningRequest(
* will encrypt and sign the new, empty, header and return it in the provided
* buffer.
*
- * The new entry should be created with a status of kUnused and all times
- * times should be set to 0.
+ * The new entry should be created with a status of OEMCrypto_Unused and all
+ * times times should be set to 0.
*
* Devices that do not implement a Session Usage Table may return
* OEMCrypto_ERROR_NOT_IMPLEMENTED.
@@ -5056,14 +5046,15 @@ OEMCryptoResult OEMCrypto_DeactivateUsageEntry(OEMCrypto_SESSION session,
*
* Valid values for status are:
*
- * - 0 = kUnused -- the keys have not been used to decrypt.
- * - 1 = kActive -- the keys have been used, and have not been deactivated.
- * - 2 = kInactive - deprecated. Use kInactiveUsed or kInactiveUnused.
- * - 3 = kInactiveUsed -- the keys have been marked inactive after being
- * active.
- * - 4 = kInactiveUnused -- they keys have been marked inactive, but were
- * never active.
- * The clock_security_level is reported as follows:
+ * - 0 = OEMCrypto_Unused -- the keys have not been used to decrypt.
+ * - 1 = OEMCrypto_Active -- the keys have been used, and have not been
+ * deactivated.
+ * - 2 = OEMCrypto_Inactive - deprecated. Use OEMCrypto_InactiveUsed or
+ * OEMCrypto_InactiveUnused.
+ * - 3 = OEMCrypto_InactiveUsed -- the keys have been marked inactive after
+ * being active.
+ * - 4 = OEMCrypto_InactiveUnused -- they keys have been marked inactive, but
+ * were never active. The clock_security_level is reported as follows:
*
* - 0 = Insecure Clock - clock just uses system time.
* - 1 = Secure Timer - clock runs from a secure timer which is initialized
@@ -5142,7 +5133,7 @@ OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
* or deactivating the license.
*
* @param[in] session: handle for the session to be used.
- * @param[out] status: the enumeration of OEMCrypto_Usage_Entry_Status.
+ * @param[out] status: the enumeration of OEMCrypto_UsageEntryStatus.
* @param[out] seconds_since_license_received: the time since the license being
* requested in seconds.
* @param[out] seconds_since_first_decrypt: the time since playback has
@@ -5163,7 +5154,7 @@ OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
* This method is new in API version 19.
*/
OEMCryptoResult OEMCrypto_GetUsageEntryInfo(
- OEMCrypto_SESSION session, OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_SESSION session, OEMCrypto_UsageEntryStatus* status,
int64_t* seconds_since_license_received,
int64_t* seconds_since_first_decrypt);
@@ -5306,19 +5297,13 @@ OEMCryptoResult OEMCrypto_GetBootCertificateChain(
size_t* additional_signature_length);
/**
- * Generates a key pair used in OEM and DRM certificate provisioning. The public
- * key is supposed to be certified by the server. The private key is wrapped
- * with the encryption key so it can be stored in the file system.
+ * Generates a key pair used in DRM certificate provisioning. The public key is
+ * supposed to be certified by the server. The private key is wrapped with the
+ * encryption key, so it can be stored in the file system.
*
- * The |public_key_signature| output is formatted differently depending
- * on whether or not an OEM private key has been loaded.
- *
- * If an OEM private key is unavailable, the request is assumed to be for OEM
- * certificate provisioning. In this case, the public key is signed by the
- * device private key. The format of |public_key_signature| in this case is a
- * COSE_Sign1 CBOR array. The format is described in RFC 8152 Section 4.2 and
- * 4.4, as well as Android IRemotelyProvisionedComponent.aidl (under
- * "SignedData")
+ * The public key is signed by the device private key. |public_key_signature| is
+ * a COSE_Sign1 CBOR array, described in RFC 8152 Section 4.2 and 4.4 as well as
+ * Android IRemotelyProvisionedComponent.aidl (under "SignedData").
*
* ~~~
* |public_key_signature|: COSE_Sign1 CBOR array
@@ -5356,35 +5341,25 @@ OEMCryptoResult OEMCrypto_GetBootCertificateChain(
* ]
* ~~~
*
- * If an OEM private key is available, the request is assumed to be for DRM
- * certificate provisioning and the public key is signed by the OEM private key.
- * If the OEM private key is an RSA key, then |public_key_signature| is the raw
- * output of the RSA sign operation with RSASSA-PSS padding. If the OEM private
- * key is an ECC key, then |public_key_signature| is the ASN.1 DER-encoded (R,S)
- * signature as specified in RFC 3279 2.2.3.
- *
- * After this function completes successfully, the session will hold a private
- * key and will be ready for a call to
- * OEMCrypto_PrepAndSignProvisioningRequest(). In particular, when this
- * function is used to generate a DRM Certificate key pair, the session will be
- * ready to sign a provisioning request with the DRM Cert private key. When this
- * function is used to generate an OEM Certificate key pair, the session will be
- * ready to sign a provisioning request with the OEM Cert private key.
+ * After this function completes successfully, the session will hold the private
+ * key and be ready for a call to OEMCrypto_PrepAndSignProvisioningRequest(). In
+ * particular, the session will be ready to sign a provisioning request with the
+ * DRM cert private key.
*
* The public key shall be an ASN.1 DER-encoded SubjectPublicKeyInfo as
* specified in RFC 5280. Widevine recommends ECC keys for Provisioning 4.0, but
* an RSA key may also be used. If the key is an RSA key, then the encoding
- * should use "rsaEncryption" (OID 1.2.840.113549.1.1.1), and not RSASSA-PSS.
+ * should use "rsaEncryption" (OID 1.2.840.113549.1.1.1) instead of RSASSA-PSS.
*
* @param[in] session: session id.
* @param[out] public_key: pointer to the buffer that receives the public key
- * that is to be certified by the server. The key must be an ASN.1
- * DER-encoded SubjectPublicKeyInfo as specified in RFC 5280.
+ * that is to be certified by the server. The key is an ASN.1 DER-encoded
+ * SubjectPublicKeyInfo as specified in RFC 5280.
* @param[in,out] public_key_length: on input, size of the caller's public_key
* buffer. On output, the number of bytes written into the buffer.
* @param[out] public_key_signature: pointer to the buffer that receives the
- * signature of the public key. The format depends on whether an OEM private
- * key has been loaded.
+ * signature of the public key. The signature is a COSE_Sign1 CBOR array as
+ * described in in RFC 8152.
* @param[in,out] public_key_signature_length: on input, size of the caller's
* public_key_signature buffer. On output, the number of bytes written into
* the buffer.
@@ -5410,7 +5385,7 @@ OEMCryptoResult OEMCrypto_GetBootCertificateChain(
* session, and a read lock on the OEMCrypto system.
*
* @version
- * This method is new in API version 17.
+ * This method was new in API version 17 and changed in API version 20.
*/
OEMCryptoResult OEMCrypto_GenerateCertificateKeyPair(
OEMCrypto_SESSION session, uint8_t* public_key, size_t* public_key_length,
@@ -5570,43 +5545,6 @@ OEMCryptoResult OEMCrypto_GetDeviceSignedCsrPayload(
const uint8_t* encoded_device_info, size_t encoded_device_info_length,
uint8_t* signed_csr_payload, size_t* signed_csr_payload_length);
-/**
- * Loads an OEM private key to a session. The key will be used in signing DRM
- * certificate request, or the public key generated by calling
- * OEMCrypto_GenerateCertificateKeyPair.
- *
- * @param[in] session: session id.
- * @param[in] key_type: type of the leaf key (RSA or ECC).
- * @param[in] wrapped_private_key: the encrypted private key. This is the
- * wrapped key generated by OEMCrypto_GenerateCertificateKeyPair.
- * @param[in] wrapped_private_key_length: length of |wrapped_private_key| in
- * bytes.
- *
- * @retval OEMCrypto_SUCCESS
- * @retval OEMCrypto_ERROR_INVALID_CONTEXT
- * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
- * @retval OEMCrypto_ERROR_INVALID_SESSION
- * @retval OEMCrypto_ERROR_INVALID_KEY
- * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
- * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
- * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
- * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
- * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
- * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
- *
- * @threading
- * This is a "Session Function" and may be called simultaneously with session
- * functions for other sessions but not simultaneously with other functions
- * for this session. It will not be called simultaneously with initialization
- * or usage table functions. It is as if the CDM holds a write lock for this
- * session, and a read lock on the OEMCrypto system.
- *
- * @version
- * This method is new in API version 17.
- */
-OEMCryptoResult OEMCrypto_InstallOemPrivateKey(
- OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
- const uint8_t* wrapped_private_key, size_t wrapped_private_key_length);
/// @}
/// @addtogroup test_verify
@@ -5850,6 +5788,37 @@ OEMCryptoResult OEMCrypto_FreeSecureBuffer(
OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor,
int secure_fd);
+/**
+ * Fill a buffer with hardware-generated random data to diagnose entropy issues.
+ *
+ * @param[out] random_data: pointer to the buffer that receives random data
+ * @param[in] random_data_length: length of the random data buffer in bytes
+ *
+ * @retval OEMCrypto_SUCCESS success
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED OEMCrypto is a production build, and
+ * does not support debug or test-only functions.
+ * @retval OEMCrypto_ERROR_RNG_FAILED
+ * @retval OEMCrypto_ERROR_BUFFER_TOO_LARGE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ *
+ * @buffer_size
+ * OEMCrypto shall support random_data_length sizes of at least 100 KiB for
+ * random number generation.
+ * OEMCrypto shall return OEMCrypto_ERROR_BUFFER_TOO_LARGE if the buffer is
+ * larger than the supported size.
+ *
+ * @threading
+ * This is a "Property Function" and may be called simultaneously with any
+ * other property function or session function, but not any initialization or
+ * usage table function, as if the CDM holds a read lock on the OEMCrypto
+ * system.
+ *
+ * @version
+ * This method changed in API version 20.
+ */
+OEMCryptoResult OEMCrypto_GetRandom(OEMCrypto_SharedMemory* random_data,
+ size_t random_data_length);
+
/// @}
/*
@@ -6082,7 +6051,7 @@ OEMCryptoResult OEMCrypto_DeleteOldUsageTable(void);
*/
OEMCryptoResult OEMCrypto_CreateOldUsageEntry(
uint64_t time_since_license_received, uint64_t time_since_first_decrypt,
- uint64_t time_since_last_decrypt, OEMCrypto_Usage_Entry_Status status,
+ uint64_t time_since_last_decrypt, OEMCrypto_UsageEntryStatus status,
uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
size_t pst_length);
@@ -6223,14 +6192,6 @@ OEMCryptoResult OEMCrypto_RefreshKeys(
const uint8_t* signature, size_t signature_length, size_t num_keys,
const OEMCrypto_KeyRefreshObject* key_array);
-/**
- * OEMCrypto_GetRandom
- * @deprecated
- * OEMCrypto_GetRandom is not needed to export random numbers.
- */
-OEMCryptoResult OEMCrypto_GetRandom(uint8_t* random_data,
- size_t random_data_length);
-
/**
* OEMCrypto_SelectKey
* @deprecated
@@ -6348,6 +6309,36 @@ OEMCryptoResult OEMCrypto_LoadProvisioning_V18(
size_t signature_length, uint8_t* wrapped_private_key,
size_t* wrapped_private_key_length);
+/**
+ * OEMCrypto_InstallOemPrivateKey
+ * TODO(b/374834498): Mark as deprecated once build system is updated
+ * to handle removing symbol.
+ * Not required for the current version of OEMCrypto. Declared here to
+ * help with backward compatibility.
+ *
+ * @param[in] session: session id.
+ * @param[in] key_type: type of the leaf key (RSA or ECC).
+ * @param[in] wrapped_private_key: the encrypted private key. This is the
+ * wrapped key generated by OEMCrypto_GenerateCertificateKeyPair.
+ * @param[in] wrapped_private_key_length: length of |wrapped_private_key| in
+ * bytes.
+ *
+ * @retval OEMCrypto_SUCCESS
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_NO_DEVICE_KEY
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_KEY
+ * @retval OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ * @retval OEMCrypto_ERROR_SESSION_LOST_STATE
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ * @retval OEMCrypto_ERROR_UNKNOWN_FAILURE
+ */
+OEMCryptoResult OEMCrypto_InstallOemPrivateKey(
+ OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key, size_t wrapped_private_key_length);
+
/****************************************************************************/
/****************************************************************************/
/* The following functions are used by internal L3 CDMs and are not required by
@@ -6398,6 +6389,44 @@ OEMCryptoResult OEMCrypto_UseSecondaryKey(OEMCrypto_SESSION session_id,
*/
OEMCryptoResult OEMCrypto_MarkOfflineSession(OEMCrypto_SESSION session);
+/**
+ * Loads the license data into the given session.
+ *
+ * @param[in] session: session id for operation.
+ * @param[in] data: the buffer to import.
+ * @param[in] data_length: the number of bytes in |data|.
+ *
+ * @ignore
+ * @retval OEMCrypto_SUCCESS on success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_SESSION_STATE_LOST
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ */
+OEMCryptoResult OEMCrypto_LoadLicenseData(OEMCrypto_SESSION session,
+ const uint8_t* data,
+ size_t data_length);
+
+/**
+ * Saves the license data for the given session.
+ *
+ * @param[in] session: session id for operation.
+ * @param[out] data: the buffer to export into.
+ * @param[in,out] data_length: (in) length of the data buffer, in bytes.
+ * (out) actual length of the data, in bytes.
+ *
+ * @ignore
+ * @retval OEMCrypto_SUCCESS on success
+ * @retval OEMCrypto_ERROR_INVALID_SESSION
+ * @retval OEMCrypto_ERROR_INVALID_CONTEXT
+ * @retval OEMCrypto_ERROR_SESSION_STATE_LOST
+ * @retval OEMCrypto_ERROR_SYSTEM_INVALIDATED
+ * @retval OEMCrypto_ERROR_NOT_IMPLEMENTED
+ */
+OEMCryptoResult OEMCrypto_SaveLicenseData(OEMCrypto_SESSION session,
+ uint8_t* data, size_t* data_length);
+
#ifdef __cplusplus
}
#endif
diff --git a/oemcrypto/include/level3.h b/oemcrypto/include/level3.h
index 4efdb82..9be64ca 100644
--- a/oemcrypto/include/level3.h
+++ b/oemcrypto/include/level3.h
@@ -25,6 +25,7 @@
#define Level3_InstallKeyboxOrOEMCert _lcc03
#define Level3_GetKeyData _lcc04
#define Level3_IsKeyboxOrOEMCertValid _lcc05
+#define Level3_GetRandom _lcc06
#define Level3_GetDeviceID _lcc07
#define Level3_WrapKeyboxOrOEMCert _lcc08
#define Level3_OpenSession _lcc09
@@ -132,12 +133,15 @@
#define Level3_GetBCCSignatureType _lcc156
#define Level3_GetPVRKey _lcc157
#define Level3_LoadPVRKey _lcc158
+#define Level3_LoadLicenseData _lcc159
+#define Level3_SaveLicenseData _lcc160
#else
#define Level3_Initialize _oecc01
#define Level3_Terminate _oecc02
#define Level3_InstallKeyboxOrOEMCert _oecc03
#define Level3_GetKeyData _oecc04
#define Level3_IsKeyboxOrOEMCertValid _oecc05
+#define Level3_GetRandom _oecc06
#define Level3_GetDeviceID _oecc07
#define Level3_WrapKeyboxOrOEMCert _oecc08
#define Level3_OpenSession _oecc09
@@ -248,6 +252,8 @@
#define Level3_GetBCCSignatureType _oecc156
#define Level3_GetPVRKey _oecc157
#define Level3_LoadPVRKey _oecc158
+#define Level3_LoadLicenseData _oecc159
+#define Level3_SaveLicenseData _oecc160
#endif
#define Level3_GetInitializationState _oecl3o01
@@ -288,6 +294,8 @@ OEMCryptoResult Level3_GetOEMPublicCertificate(uint8_t* public_cert,
size_t* public_cert_length);
OEMCryptoResult Level3_GetDeviceID(uint8_t* deviceID, size_t* idLength);
OEMCryptoResult Level3_GetKeyData(uint8_t* keyData, size_t* keyDataLength);
+OEMCryptoResult Level3_GetRandom(OEMCrypto_SharedMemory* randomData,
+ size_t randomDataLength);
OEMCryptoResult Level3_LoadOEMPrivateKey(OEMCrypto_SESSION session);
OEMCryptoResult Level3_LoadDRMPrivateKey(OEMCrypto_SESSION session,
OEMCrypto_PrivateKeyType key_type,
@@ -353,6 +361,10 @@ OEMCryptoResult Level3_DeactivateUsageEntry(OEMCrypto_SESSION session,
OEMCryptoResult Level3_ReportUsage(OEMCrypto_SESSION session,
const uint8_t* pst, size_t pst_length,
uint8_t* buffer, size_t* buffer_length);
+OEMCryptoResult Level3_GetUsageEntryInfo(
+ OEMCrypto_SESSION session, OEMCrypto_UsageEntryStatus* status,
+ int64_t* seconds_since_license_received,
+ int64_t* seconds_since_first_decrypt);
bool Level3_IsSRMUpdateSupported();
OEMCryptoResult Level3_GetCurrentSRMVersion(uint16_t* version);
OEMCryptoResult Level3_LoadSRM(const uint8_t* buffer, size_t buffer_length);
@@ -413,6 +425,12 @@ OEMCryptoResult Level3_LoadRenewal(OEMCrypto_SESSION session,
size_t core_message_length,
const uint8_t* signature,
size_t signature_length);
+OEMCryptoResult Level3_LoadRelease(OEMCrypto_SESSION session,
+ const uint8_t* message,
+ size_t message_length,
+ size_t core_message_length,
+ const uint8_t* signature,
+ size_t signature_length);
OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
@@ -435,6 +453,9 @@ OEMCryptoResult Level3_PrepAndSignLicenseRequest(
OEMCryptoResult Level3_PrepAndSignRenewalRequest(
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
+OEMCryptoResult Level3_PrepAndSignReleaseRequest(
+ OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
+ size_t* core_message_size, uint8_t* signature, size_t* signature_length);
size_t Level3_MaximumUsageTableHeaderSize();
OEMCryptoResult Level3_AllocateSecureBuffer(
OEMCrypto_SESSION session, size_t buffer_size,
@@ -555,6 +576,10 @@ OEMCryptoResult Level3_GetEmbeddedDrmCertificate(uint8_t* public_cert,
OEMCryptoResult Level3_UseSecondaryKey(OEMCrypto_SESSION session_id,
bool dual_key);
OEMCryptoResult Level3_MarkOfflineSession(OEMCrypto_SESSION session_id);
+OEMCryptoResult Level3_LoadLicenseData(OEMCrypto_SESSION session,
+ const uint8_t* data, size_t data_length);
+OEMCryptoResult Level3_SaveLicenseData(OEMCrypto_SESSION session, uint8_t* data,
+ size_t* data_length);
OEMCryptoResult Level3_GetBCCSignatureType(
OEMCrypto_BCCSignatureType* bcc_signature_type);
diff --git a/oemcrypto/odk/Android.bp b/oemcrypto/odk/Android.bp
index 6b966ce..8518b94 100644
--- a/oemcrypto/odk/Android.bp
+++ b/oemcrypto/odk/Android.bp
@@ -9,6 +9,7 @@
// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
// DEPENDING ON IT IN YOUR PROJECT. ***
package {
+ default_team: "trendy_team_media_framework_drm",
// 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"
@@ -18,17 +19,49 @@ package {
default_applicable_licenses: ["vendor_widevine_license"],
}
-cc_library_static {
- name: "libwv_odk",
- include_dirs: [
- "vendor/widevine/libwvdrmengine/oemcrypto/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/src",
+// Header library for public ODK struct definitions.
+// This intended for targets which need access to C struct definitions,
+// but not the library functions (ex. corpus generator).
+//
+// Note: This header library technically exposes the API in addition to
+// the struct definitions; however, the API is not intended to be used
+// directly by dependencies.
+cc_library_headers {
+ name: "odk_struct_headers",
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ owner: "widevine",
+ min_sdk_version: "34",
+}
+
+// ----------------------------------------------------------------
+// Builds: libwv_odk.a
+// The ODK Library - TEE (and sometimes REE) library for preparing
+// and parsing client-side core messages.
+cc_defaults {
+ name: "libwv_odk_defaults",
+ defaults: [
+ "widevine_code_protected",
+ ],
+
+ // Includes for building.
+ local_include_dirs: [
+ "include",
+ "src",
],
header_libs: [
- "jni_headers",
- "libbase_headers",
- "liblog_headers",
+ "oemcrypto_api_headers",
+ ],
+
+ // Includes for components using libwv_odk.a.
+ export_include_dirs: [
+ "include",
+ ],
+ export_header_lib_headers: [
+ "oemcrypto_api_headers",
],
srcs: [
@@ -40,53 +73,96 @@ cc_library_static {
"src/odk_util.c",
"src/serialization_base.c",
],
- proprietary: true,
owner: "widevine",
min_sdk_version: "34",
}
-// ----------------------------------------------------------------
-// Builds libwv_kdo.a, The ODK Library companion (libwv_kdo) is used by
-// the CDM and by oemcrypto tests, but not by oemcrypto implementations.
cc_library_static {
- name: "libwv_kdo",
- include_dirs: [
- "vendor/widevine/libwvdrmengine/oemcrypto/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/src",
+ name: "libwv_odk",
+
+ defaults: ["libwv_odk_defaults"],
+ proprietary: true,
+}
+
+cc_library_static {
+ name: "libwv_odk.system",
+
+ defaults: ["libwv_odk_defaults"],
+ system_ext_specific: true,
+}
+
+// ----------------------------------------------------------------
+// Builds: libwv_kdo.a
+// The ODK Library companion - Server (and sometimes REE) library
+// for preparing and parsing server-side core messages.
+cc_defaults {
+ name: "libwv_kdo_defaults",
+ defaults: [
+ "widevine_code_protected",
+ ],
+
+ // Includes for building.
+ local_include_dirs: [
+ "include",
+ "src",
],
header_libs: [
- "jni_headers",
- "libbase_headers",
- "liblog_headers",
+ "oemcrypto_api_headers",
+ ],
+
+ // Includes for components using libwv_kdo.a.
+ export_include_dirs: [
+ "include",
+ ],
+ export_header_lib_headers: [
+ "oemcrypto_api_headers",
],
srcs: [
- "src/core_message_deserialize.cpp",
- "src/core_message_features.cpp",
- "src/core_message_serialize.cpp",
- "src/core_message_serialize_proto.cpp",
+ "src/core_message_deserialize.cpp",
+ "src/core_message_features.cpp",
+ "src/core_message_serialize.cpp",
+ "src/core_message_serialize_proto.cpp",
],
+ owner: "widevine",
+}
+
+cc_library_static {
+ name: "libwv_kdo",
+
+ defaults: ["libwv_kdo_defaults"],
+ proprietary: true,
+
static_libs: [
"libcdm_protos",
"libwv_odk",
],
+}
- proprietary: true,
+cc_library_static {
+ name: "libwv_kdo.system",
- owner: "widevine",
+ defaults: ["libwv_kdo_defaults"],
+ system_ext_specific: true,
+
+ static_libs: [
+ "libcdm_protos.system",
+ "libwv_odk.system",
+ ],
}
// ----------------------------------------------------------------
-// Builds odk_test executable, which tests the ODK library.
+// Builds: odk_test executable
+// Unittests for the ODK library.
cc_test {
name: "odk_test",
- include_dirs: [
- "vendor/widevine/libwvdrmengine/oemcrypto/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/src",
+
+ // Includes for building.
+ local_include_dirs: [
+ "src",
+ "test",
],
// WARNING: Module tags are not supported in Soong.
@@ -96,11 +172,16 @@ cc_test {
// - Both 32 & 64 bit versions will be built (as appropriate)
owner: "widevine",
+ team: "trendy_team_media_framework_drm",
proprietary: true,
+ // Required to run as module tests in ATP
+ test_suites: ["general-tests"],
+ gtest: true,
+ require_root: true,
+
static_libs: [
"libcdm_protos",
- "libcdm",
"libwv_odk",
"libwv_kdo",
],
@@ -118,5 +199,4 @@ cc_test {
"test/odk_test_helper.cpp",
"test/odk_timer_test.cpp",
],
-
}
diff --git a/oemcrypto/odk/include/OEMCryptoCENCCommon.h b/oemcrypto/odk/include/OEMCryptoCENCCommon.h
index ffc70ab..7caed4a 100644
--- a/oemcrypto/odk/include/OEMCryptoCENCCommon.h
+++ b/oemcrypto/odk/include/OEMCryptoCENCCommon.h
@@ -76,9 +76,10 @@ typedef enum OEMCryptoResult {
OEMCrypto_ERROR_LICENSE_INACTIVE = 47,
OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE = 48,
OEMCrypto_ERROR_ENTRY_IN_USE = 49,
- OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50, /* Obsolete. Don't use. */
- /* Use OEMCrypto_ERROR_NO_CONTENT_KEY instead of KEY_NOT_LOADED. */
- OEMCrypto_KEY_NOT_LOADED = 51, /* Obsolete. */
+ /** Obsolete. Don't use. */
+ OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50,
+ /** Obsolete. Use OEMCrypto_ERROR_NO_CONTENT_KEY instead of KEY_NOT_LOADED. */
+ OEMCrypto_KEY_NOT_LOADED = 51,
OEMCrypto_KEY_NOT_ENTITLED = 52,
OEMCrypto_ERROR_BAD_HASH = 53,
OEMCrypto_ERROR_OUTPUT_TOO_LARGE = 54,
@@ -115,13 +116,14 @@ typedef enum OEMCryptoResult {
/**
* Valid values for status in the usage table.
*/
-typedef enum OEMCrypto_Usage_Entry_Status {
- kUnused = 0,
- kActive = 1,
- kInactive = 2, /* Deprecated. Use kInactiveUsed or kInactiveUnused. */
- kInactiveUsed = 3,
- kInactiveUnused = 4,
-} OEMCrypto_Usage_Entry_Status;
+typedef enum OEMCrypto_UsageEntryStatus {
+ OEMCrypto_Unused = 0,
+ OEMCrypto_Active = 1,
+ OEMCrypto_Inactive = 2, // Deprecated. Use OEMCrypto_InactiveUsed or
+ // OEMCrypto_InactiveUnused.
+ OEMCrypto_InactiveUsed = 3,
+ OEMCrypto_InactiveUnused = 4,
+} OEMCrypto_UsageEntryStatus;
/* Not used publicly. Not documented with Doxygen. */
typedef enum OEMCrypto_ProvisioningRenewalType {
@@ -143,9 +145,9 @@ typedef enum OEMCrypto_LicenseType {
* Private key type used in the provisioning response.
*/
typedef enum OEMCrypto_PrivateKeyType {
- OEMCrypto_RSA_Private_Key = 0,
- OEMCrypto_ECC_Private_Key = 1,
- OEMCrypto_PrivateKeyType_MaxValue = OEMCrypto_ECC_Private_Key,
+ OEMCrypto_RSAPrivateKey = 0,
+ OEMCrypto_ECCPrivateKey = 1,
+ OEMCrypto_PrivateKeyType_MaxValue = OEMCrypto_ECCPrivateKey,
} OEMCrypto_PrivateKeyType;
/**
@@ -153,10 +155,10 @@ typedef enum OEMCrypto_PrivateKeyType {
* starts.
*/
typedef enum OEMCrypto_TimerDelayBase {
- OEMCrypto_License_Start = 0,
- OEMCrypto_License_Load = 1,
- OEMCrypto_First_Decrypt = 2,
- OEMCrypto_TimerDelayBase_MaxValue = OEMCrypto_First_Decrypt,
+ OEMCrypto_LicenseStart = 0,
+ OEMCrypto_LicenseLoad = 1,
+ OEMCrypto_FirstDecrypt = 2,
+ OEMCrypto_TimerDelayBase_MaxValue = OEMCrypto_FirstDecrypt,
} OEMCrypto_TimerDelayBase;
/**
@@ -254,6 +256,102 @@ typedef struct {
OEMCrypto_Substring key_control;
} OEMCrypto_KeyObject;
+/**
+ * Valid values for clock_security_level in OEMCrypto_PST_Report.
+ */
+typedef enum OEMCrypto_ClockSecurityLevel {
+ OEMCrypto_InsecureClock = 0,
+ OEMCrypto_MonotonicClock = 1,
+ OEMCrypto_SecureTimer = 1, // DEPRECATED. Do not use.
+ OEMCrypto_SecureClock = 2,
+ OEMCrypto_HardwareSecureClock = 3
+} OEMCrypto_ClockSecurityLevel;
+
+/**
+ * Content mitigation option for DeCENC attacks.
+ *
+ * For this enum, multiples of 2 will be used for the DeCENC mitigation options
+ * in order to correlate to how mitigation options are supported via bitmask.
+ */
+typedef enum OEMCrypto_DeCENC_Mitigation_Option {
+ OEMCrypto_DeCENC_Mitigation_Option_None = 0,
+ /** If the device can authenticate the signature of the bitstream. This is
+ the "long term" solution that requires the content stream to be signed by a
+ new key.
+ */
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream = 1,
+ /** If the device can validate the bitstream. This means that OEMCrypto will
+ parse the decrypted bit stream and replace any I_PCM blocks with zeros. */
+ OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream = 2,
+ /** If the device can restrict the decoding. This means that the codec will
+ parse the decrypted bit stream as usual, but will **not** pass through any
+ I_PCM blocks. */
+ OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding = 4,
+ OEMCrypto_DeCENC_Mitigation_Option_MaxValue =
+ OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding,
+} OEMCrypto_DeCENC_Mitigation_Option;
+
+/**
+ * Authentication key information for chosen DeCENC mitigation.
+ */
+typedef struct {
+ OEMCrypto_Substring authentication_key;
+ OEMCrypto_Substring authentication_key_iv;
+} OEMCrypto_AuthenticationKeyInfo;
+
+/**
+ * Information about the required DeCENC mitigation option and the configuration
+ * options for the mitigation option.
+ * @param mitigation_option: the DeCENC mitigation option that the content
+ * provider wants to use for the key.
+ * @param configuration_options: optional configuration options to be used with
+ * required_decenc_mitigation.
+ */
+typedef struct {
+ OEMCrypto_DeCENC_Mitigation_Option mitigation_option;
+ union {
+ // Configuration option for OEMCrypto_DeCENC_Mitigation_Option = 1 where
+ // the bitstream is authenticated.
+ OEMCrypto_AuthenticationKeyInfo authentication_key_info;
+ } configuration_options;
+} OEMCrypto_DeCENC_Mitigation_Info;
+
+/**
+ * Version 2 of OEMCrypto_KeyObject. Created for DeCENC attack mitigation which
+ * needs extra fields.
+ *
+ * Points to the relevant fields for a content key. The fields are extracted
+ * from the License Response message offered to ODK_ParseLicense(). Each
+ * field points to one of the components of the key. Key data, key control,
+ * and both IV fields are 128 bits (16 bytes):
+ * @param key_id: the unique id of this key.
+ * @param key_id_length: the size of key_id. OEMCrypto may assume this is at
+ * most 16. However, OEMCrypto shall correctly handle key id lengths
+ * from 1 to 16 bytes.
+ * @param key_data_iv: the IV for performing AES-128-CBC decryption of the
+ * key_data field.
+ * @param key_data - the key data. It is encrypted (AES-128-CBC) with the
+ * session's derived encrypt key and the key_data_iv.
+ * @param key_control_iv: the IV for performing AES-128-CBC decryption of the
+ * key_control field.
+ * @param key_control: the key control block. It is encrypted (AES-128-CBC) with
+ * the content key from the key_data field.
+ * @param decenc_mitigation_info: the DeCENC mitigation option that the
+ * content provider wants to use for the key and the configuration
+ * options for the mitigation option.
+ *
+ * The memory for the OEMCrypto_KeyObject fields is allocated and freed
+ * by the caller of ODK_ParseLicense().
+ */
+typedef struct {
+ OEMCrypto_Substring key_id;
+ OEMCrypto_Substring key_data_iv;
+ OEMCrypto_Substring key_data;
+ OEMCrypto_Substring key_control_iv;
+ OEMCrypto_Substring key_control;
+ OEMCrypto_DeCENC_Mitigation_Info decenc_mitigation_info;
+} OEMCrypto_KeyObjectV2;
+
/// @}
#ifdef __cplusplus
diff --git a/oemcrypto/odk/include/core_message_deserialize.h b/oemcrypto/odk/include/core_message_deserialize.h
index fb80dc5..74c3a7a 100644
--- a/oemcrypto/odk/include/core_message_deserialize.h
+++ b/oemcrypto/odk/include/core_message_deserialize.h
@@ -99,6 +99,18 @@ bool CoreRenewedProvisioningRequestFromMessage(
bool CoreCommonRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_CommonRequest* core_common_request);
+/**
+ * Counterpart (deserializer) of decenc_mitigation_options_supported in
+ * ODK_PrepareCoreLicenseRequest (serializer)
+ *
+ * Parameters:
+ * [in] oemcrypto_core_message
+ * [out] decenc_mitigation_options_supported
+ */
+bool CoreDecencMitigationOptionsSupportedFromMessage(
+ const std::string& oemcrypto_core_message,
+ uint16_t& decenc_mitigation_options_supported);
+
} // namespace deserialize
} // namespace oemcrypto_core_message
diff --git a/oemcrypto/odk/include/core_message_features.h b/oemcrypto/odk/include/core_message_features.h
index 3edfc02..d4d3531 100644
--- a/oemcrypto/odk/include/core_message_features.h
+++ b/oemcrypto/odk/include/core_message_features.h
@@ -18,11 +18,23 @@ namespace features {
// this structure, we can turn off features at runtime. This is plain data, and
// is essentially a version number.
struct CoreMessageFeatures {
+ // If |prerelease_odk_messages| is true, then the server will serve prerelease
+ // devices.
+ explicit CoreMessageFeatures(bool prerelease_odk_messages = false);
+
// 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);
+ // Create the default feature set for the given major version number. This
+ // function should only be used when running tests, or in special cases where
+ // a license is being generated out of band, like for an ATSC license.
+ static CoreMessageFeatures DefaultFeatures(
+ uint32_t maximum_major_version,
+ bool serve_prerelease_odk_messages = false);
+
+ // If this is true, then the server should serve messages to a prerelease
+ // device. If this is false, requests from a prerelease device are rejected.
+ bool serve_prerelease_odk_messages = false;
// 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
@@ -34,6 +46,19 @@ struct CoreMessageFeatures {
bool operator!=(const CoreMessageFeatures &other) const {
return !(*this == other);
}
+
+ // Verify that the give version number is valid. If the version is prerelease,
+ // and serve_prereease_messages is false, then this returns false.
+ bool ValidateRequestVersion(uint16_t major_version,
+ uint16_t minor_version) const;
+
+ // Compute the minimum of the feature version and the request version. Return
+ // false if the request is prerelease and the serve_prerelease_messages is
+ // false.
+ bool GetResponseVersion(uint16_t request_major_version,
+ uint16_t request_minor_version,
+ uint16_t &response_major_version,
+ uint16_t &response_minor_version) const;
};
std::ostream &operator<<(std::ostream &os, const CoreMessageFeatures &features);
diff --git a/oemcrypto/odk/include/core_message_serialize.h b/oemcrypto/odk/include/core_message_serialize.h
index 64e9427..40371e6 100644
--- a/oemcrypto/odk/include/core_message_serialize.h
+++ b/oemcrypto/odk/include/core_message_serialize.h
@@ -51,14 +51,10 @@ bool CreateCoreLicenseResponse(const CoreMessageFeatures& features,
* Parameters:
* [in] features feature support for response message.
* [in] core_request
- * [in] seconds_since_license_requested
- * [in] seconds_since_first_decrypt
* [out] oemcrypto_core_message
*/
bool CreateCoreReleaseResponse(const CoreMessageFeatures& features,
const ODK_ReleaseRequest& core_request,
- int64_t seconds_since_license_requested,
- int64_t seconds_since_first_decrypt,
std::string* oemcrypto_core_message);
/**
diff --git a/oemcrypto/odk/include/odk.h b/oemcrypto/odk/include/odk.h
index 679d4e0..a29a0c3 100644
--- a/oemcrypto/odk/include/odk.h
+++ b/oemcrypto/odk/include/odk.h
@@ -158,7 +158,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
uint64_t time_of_license_request_signed,
uint64_t time_of_first_decrypt,
uint64_t time_of_last_decrypt,
- enum OEMCrypto_Usage_Entry_Status status,
+ enum OEMCrypto_UsageEntryStatus status,
uint64_t system_time_seconds);
/**
@@ -263,7 +263,9 @@ OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
* bytes. (out) actual length of the core message, in bytes.
* @param[in] nonce_values: pointer to the session's nonce data.
* @param[in] message_count_info: information used for server-side anomaly
- * detection
+ * detection
+ * @param[in] decenc_mitigation_options_supported: the supported decenc
+ * mitigation options from the device.
*
* @retval OEMCrypto_SUCCESS
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
@@ -275,7 +277,8 @@ OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values);
OEMCryptoResult ODK_PrepareCoreLicenseRequest(
uint8_t* message, size_t message_length, size_t* core_message_size,
const ODK_NonceValues* nonce_values,
- const ODK_MessageCounterInfo* counter_info);
+ const ODK_MessageCounterInfo* counter_info,
+ uint16_t decenc_mitigation_options_supported);
/**
* Modifies the message to include a core license release at the beginning of
@@ -295,13 +298,16 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
* 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] status: the enumeration of OEMCrypto_Usage_Entry_Status
+ * @param[in] usage_entry_status: the enumeration of
+ * OEMCrypto_UsageEntryStatus
* @param[in] clock_security_level: the enumeration of
* OEMCryto_Clock_Security_Level
* @param[in] seconds_since_license_requested: the time between the license
* being requested and the release being generated in seconds
* @param[in] seconds_since_first_decrypt: The time since playback has started
* in seconds
+ * @param[in] pst: the provider session token.
+ * @param[in] pst_length: the length of the pst array.
* @param[in,out] clock_values: the session's clock values.
* @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
* seconds.
@@ -311,14 +317,15 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
* @retval OEMCrypto_ERROR_INVALID_CONTEXT
*
* @version
- * This method is new in version 19 of the API.
+ * This method is new in version 20 of the API.
*/
OEMCryptoResult ODK_PrepareCoreReleaseRequest(
uint8_t* message, size_t message_length, size_t* core_message_size,
- ODK_NonceValues* nonce_values, uint32_t status,
- uint32_t clock_security_level, int64_t seconds_since_license_requested,
- int64_t seconds_since_first_decrypt, ODK_ClockValues* clock_values,
- uint64_t system_time_seconds);
+ ODK_NonceValues* nonce_values,
+ OEMCrypto_UsageEntryStatus usage_entry_status,
+ uint32_t clock_security_level, uint64_t seconds_since_license_requested,
+ uint64_t seconds_since_first_decrypt, const uint8_t* pst, size_t pst_length,
+ ODK_ClockValues* clock_values, uint64_t system_time_seconds);
/**
* Modifies the message to include a core renewal request at the beginning of
diff --git a/oemcrypto/odk/include/odk_message.h b/oemcrypto/odk/include/odk_message.h
index aedd31a..648eade 100644
--- a/oemcrypto/odk/include/odk_message.h
+++ b/oemcrypto/odk/include/odk_message.h
@@ -5,14 +5,14 @@
#ifndef WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
#define WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* 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
diff --git a/oemcrypto/odk/include/odk_structs.h b/oemcrypto/odk/include/odk_structs.h
index 0b905aa..e0f4dc6 100644
--- a/oemcrypto/odk/include/odk_structs.h
+++ b/oemcrypto/odk/include/odk_structs.h
@@ -5,21 +5,21 @@
#ifndef WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
#define WIDEVINE_ODK_INCLUDE_ODK_STRUCTS_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include "OEMCryptoCENCCommon.h"
#include "odk_target.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* The version of this library. */
-#define ODK_MAJOR_VERSION 19
-#define ODK_MINOR_VERSION 5
+#define ODK_MAJOR_VERSION 20
+#define ODK_MINOR_VERSION 0
/* ODK Version string. Date changed automatically on each release. */
-#define ODK_RELEASE_DATE "ODK v19.5 2025-03-11"
+#define ODK_RELEASE_DATE "ODK v20.0 2025-05-20"
/* The lowest version number for an ODK message. */
#define ODK_FIRST_VERSION 16
@@ -33,6 +33,7 @@ extern "C" {
* https://www.rfc-editor.org/rfc/rfc8949.html#name-specification-of-the-cbor-e
* for an estimation of the required length. */
#define ODK_DEVICE_INFO_LEN_MAX 768
+#define ODK_PST_LEN_MAX 256
/// @addtogroup odk_timer
/// @{
@@ -127,7 +128,7 @@ typedef struct {
uint64_t time_of_renewal_request;
uint64_t time_when_timer_expires;
uint32_t timer_status;
- enum OEMCrypto_Usage_Entry_Status status;
+ enum OEMCrypto_UsageEntryStatus status;
} ODK_ClockValues;
/**
@@ -227,6 +228,10 @@ typedef struct {
* @param dtcp2_required: indicates dtcp2 requirements of the license.
* @param renewal_delay_base: indicates which time is used for the renewal timer
* and playback timer starting point.
+ * @param decenc_mitigation_option_used: indicates whether DeCENC
+ * mitigation is used. Used to determine packing/unpacking of DeCENC
+ * fields in the key object. This field represents a boolean (zero or
+ * nonzero).
* @param key_array_length: number of keys present.
* @param key_array: set of keys to be installed.
*
@@ -244,8 +249,12 @@ typedef struct {
uint32_t watermarking;
OEMCrypto_DTCP2_CMI_Packet dtcp2_required;
OEMCrypto_TimerDelayBase renewal_delay_base;
- uint32_t key_array_length;
- OEMCrypto_KeyObject key_array[ODK_MAX_NUM_KEYS];
+ uint16_t decenc_mitigation_option_used;
+ uint16_t key_array_length;
+ // If |decenc_mitigation_option_used| is 0, then the key object V2 array will
+ // be treated like an array of OEMCrypto_KeyObject. The extra fields in
+ // OEMCrypto_KeyObjectV2 will be ignored.
+ OEMCrypto_KeyObjectV2 key_array[ODK_MAX_NUM_KEYS];
} ODK_ParsedLicense;
/**
@@ -267,12 +276,15 @@ typedef struct {
* @param dtcp2_required: indicates dtcp2 requirements of the license.
* @param renewal_delay_base: indicates which time is used for the renewal timer
* and playback timer starting point.
+ * @param decenc_mitigation_option_used: indicates whether DeCENC
+ * mitigation is used. Used to determine packing/unpacking of DeCENC
+ * fields in the key object.
* @param key_array_length: number of keys present.
* @param key_array: set of keys to be installed. This is a pointer to an array
* to allow packing a number of keys greater than |ODK_MAX_NUM_KEYS|.
*
* @version
- * This struct changed in API version 18.
+ * This struct changed in API version 19.
*/
typedef struct {
OEMCrypto_Substring enc_mac_keys_iv;
@@ -285,8 +297,9 @@ typedef struct {
uint32_t watermarking;
OEMCrypto_DTCP2_CMI_Packet dtcp2_required;
OEMCrypto_TimerDelayBase renewal_delay_base;
- uint32_t key_array_length;
- OEMCrypto_KeyObject* key_array;
+ uint16_t decenc_mitigation_option_used;
+ uint16_t key_array_length;
+ OEMCrypto_KeyObjectV2* key_array;
} ODK_Packing_ParsedLicense;
/**
@@ -299,15 +312,24 @@ typedef struct {
* @param enc_private_key_iv: IV for decrypting new private key. Size is 128
* bits.
* @param encrypted_message_key: used for provisioning 3.0 to derive keys.
+ * @param curr_server_sealing_key: the server sealing key for the current
+ * firmware version.
+ * @param server_sealing_key_array_length: number of server sealing keys present
+ * for previous versions.
+ * @param server_sealing_key_array: set of server sealing keys for previous
+ * firmware versions. Set to a maximum of 5 for now.
*
* @version
- * This struct changed in API version 16.2.
+ * This struct changed in API version 20.0.
*/
typedef struct {
OEMCrypto_PrivateKeyType key_type;
OEMCrypto_Substring enc_private_key;
OEMCrypto_Substring enc_private_key_iv;
OEMCrypto_Substring encrypted_message_key; /* Used for Prov 3.0 */
+ OEMCrypto_Substring curr_server_sealing_key;
+ uint32_t server_sealing_key_array_length;
+ OEMCrypto_Substring server_sealing_key_array[ODK_MAX_NUM_SERVER_SEALING_KEYS];
} ODK_ParsedProvisioning;
/// @}
diff --git a/oemcrypto/odk/include/odk_target.h b/oemcrypto/odk/include/odk_target.h
index 825a263..98eca91 100644
--- a/oemcrypto/odk/include/odk_target.h
+++ b/oemcrypto/odk/include/odk_target.h
@@ -9,5 +9,6 @@
// Maximum number of keys can be modified to suit target's resource tier.
#define ODK_MAX_NUM_KEYS 32
+#define ODK_MAX_NUM_SERVER_SEALING_KEYS 5
#endif // WIDEVINE_ODK_INCLUDE_ODK_TARGET_H_
diff --git a/oemcrypto/odk/src/core_message_deserialize.cpp b/oemcrypto/odk/src/core_message_deserialize.cpp
index e1cdbd0..f0a4634 100644
--- a/oemcrypto/odk/src/core_message_deserialize.cpp
+++ b/oemcrypto/odk/src/core_message_deserialize.cpp
@@ -4,7 +4,8 @@
#include "core_message_deserialize.h"
-#include
+#include
+
#include
#include
#include
@@ -38,7 +39,7 @@ bool ParseRequest(uint32_t message_type,
}
const uint8_t* buf =
- reinterpret_cast(oemcrypto_core_message.c_str());
+ reinterpret_cast(oemcrypto_core_message.data());
const size_t buf_length = oemcrypto_core_message.size();
ODK_Message msg = ODK_Message_Create(const_cast(buf), buf_length);
@@ -89,19 +90,18 @@ bool ParseRequest(uint32_t message_type,
return true;
}
-} // namespace
-
-static bool GetNonceFromMessage(const std::string& oemcrypto_core_message,
- ODK_NonceValues* nonce_values) {
+bool GetNonceFromMessage(const std::string& oemcrypto_core_message,
+ ODK_NonceValues* nonce_values) {
if (nonce_values == nullptr) return false;
if (oemcrypto_core_message.size() < sizeof(ODK_CoreMessage)) return false;
- ODK_CoreMessage core_message;
const uint8_t* buf =
- reinterpret_cast(oemcrypto_core_message.c_str());
+ reinterpret_cast(oemcrypto_core_message.data());
ODK_Message msg = ODK_Message_Create(const_cast(buf),
oemcrypto_core_message.size());
ODK_Message_SetSize(&msg, sizeof(ODK_CoreMessage));
+
+ ODK_CoreMessage core_message = {};
Unpack_ODK_CoreMessage(&msg, &core_message);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK) return false;
*nonce_values = core_message.nonce_values;
@@ -109,7 +109,7 @@ static bool GetNonceFromMessage(const std::string& oemcrypto_core_message,
}
bool CopyCounterInfo(ODK_MessageCounter* dest, ODK_MessageCounterInfo* src) {
- if (!src || !dest) return false;
+ if (src == nullptr || dest == nullptr) return false;
dest->master_generation_number = src->master_generation_number;
dest->license_count = src->license_count;
@@ -125,9 +125,21 @@ bool CopyCounterInfo(ODK_MessageCounter* dest, ODK_MessageCounterInfo* src) {
return true;
}
+// Checks if the buffer is padded with zeros after |buffer_length|
+// up to the given |max_length|.
+bool IsBufferZeroPadded(const uint8_t* buffer, size_t buffer_length,
+ size_t max_length) {
+ if (buffer == nullptr || buffer_length > max_length) return false;
+ for (size_t i = buffer_length; i < max_length; ++i) {
+ if (buffer[i] != 0) return false;
+ }
+ return true;
+}
+} // namespace
+
bool CoreLicenseRequestFromMessage(const std::string& oemcrypto_core_message,
ODK_LicenseRequest* core_license_request) {
- ODK_NonceValues nonce;
+ ODK_NonceValues nonce = {};
if (!GetNonceFromMessage(oemcrypto_core_message, &nonce)) return false;
if (nonce.api_major_version <= 17) {
const auto unpacker = Unpack_ODK_PreparedLicenseRequestV17;
@@ -174,7 +186,7 @@ bool CoreProvisioningRequestFromMessage(
ODK_ProvisioningRequest* core_provisioning_request) {
// Need to partially parse in order to get the nonce values, which will tell
// us the major/minor version
- ODK_NonceValues nonce;
+ ODK_NonceValues nonce = {};
if (!GetNonceFromMessage(oemcrypto_core_message, &nonce)) return false;
if (nonce.api_major_version >= 18) {
@@ -204,19 +216,19 @@ bool CoreProvisioningRequestFromMessage(
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;
}
+ const uint8_t* device_id = prepared_provision.device_id;
if (device_id_length > 0) {
- uint8_t zero[ODK_DEVICE_ID_LEN_MAX] = {};
- if (memcmp(zero, device_id + device_id_length,
- ODK_DEVICE_ID_LEN_MAX - device_id_length) != 0) {
+ // Ensure all bytes after the set device ID bytes are zero.
+ if (!IsBufferZeroPadded(device_id, device_id_length,
+ ODK_DEVICE_ID_LEN_MAX)) {
return false;
}
- core_provisioning_request->device_id.assign(
- reinterpret_cast(device_id), device_id_length);
+ core_provisioning_request->device_id.assign(device_id,
+ device_id + device_id_length);
}
core_provisioning_request->renewal_type = OEMCrypto_NoRenewal;
core_provisioning_request->renewal_data.clear();
@@ -237,18 +249,18 @@ bool CoreProvisioning40RequestFromMessage(
&prepared_provision.counter_info)) {
return false;
}
- const uint8_t* device_info = prepared_provision.device_info;
const uint32_t device_info_length = prepared_provision.device_info_length;
if (device_info_length > ODK_DEVICE_INFO_LEN_MAX) {
return false;
}
- uint8_t zero[ODK_DEVICE_INFO_LEN_MAX] = {};
- if (memcmp(zero, device_info + device_info_length,
- ODK_DEVICE_INFO_LEN_MAX - device_info_length) != 0) {
+ const uint8_t* device_info = prepared_provision.device_info;
+ // Ensure all bytes after the set device info bytes are zero.
+ if (!IsBufferZeroPadded(device_info, device_info_length,
+ ODK_DEVICE_INFO_LEN_MAX)) {
return false;
}
core_provisioning_request->device_info.assign(
- reinterpret_cast(device_info), device_info_length);
+ device_info, device_info + device_info_length);
return true;
}
@@ -262,27 +274,25 @@ bool CoreRenewedProvisioningRequestFromMessage(
&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) != 0) {
+ const uint8_t* device_id = prepared_provision.device_id;
+ if (!IsBufferZeroPadded(device_id, device_id_length, ODK_DEVICE_ID_LEN_MAX)) {
return false;
}
- core_provisioning_request->device_id.assign(
- reinterpret_cast(device_id), device_id_length);
+ core_provisioning_request->device_id.assign(device_id,
+ device_id + device_id_length);
- if (prepared_provision.renewal_data_length >
- sizeof(prepared_provision.renewal_data)) {
+ const uint32_t renewal_data_length = prepared_provision.renewal_data_length;
+ if (renewal_data_length > sizeof(prepared_provision.renewal_data)) {
return false;
}
+ const uint8_t* renewal_data = prepared_provision.renewal_data;
core_provisioning_request->renewal_type = OEMCrypto_RenewalACert;
core_provisioning_request->renewal_data.assign(
- reinterpret_cast(prepared_provision.renewal_data),
- prepared_provision.renewal_data_length);
+ renewal_data, renewal_data + renewal_data_length);
return true;
}
@@ -302,5 +312,29 @@ bool CoreCommonRequestFromMessage(const std::string& oemcrypto_core_message,
return success;
}
+bool CoreDecencMitigationOptionsSupportedFromMessage(
+ const std::string& oemcrypto_core_message,
+ uint16_t& decenc_mitigation_options_supported) {
+ ODK_NonceValues nonce = {};
+ if (!GetNonceFromMessage(oemcrypto_core_message, &nonce)) return false;
+ // DeCENC mitigation options are only supported in v18.0 and above.
+ if (nonce.api_major_version >= 18) {
+ const auto unpacker = Unpack_ODK_PreparedLicenseRequest;
+ ODK_LicenseRequest core_license_request;
+ ODK_PreparedLicenseRequest prepared_license = {};
+ if (!ParseRequest(ODK_License_Request_Type, oemcrypto_core_message,
+ &core_license_request, &prepared_license, unpacker)) {
+ return false;
+ }
+ decenc_mitigation_options_supported =
+ prepared_license.decenc_mitigation_options_supported;
+ return true;
+ }
+ // For V17 and below, DeCENC mitigation options are not supported. Function
+ // will not return false, but |decenc_mitigation_options_supported| returns 0
+ // by default.
+ return true;
+}
+
} // namespace deserialize
} // namespace oemcrypto_core_message
diff --git a/oemcrypto/odk/src/core_message_features.cpp b/oemcrypto/odk/src/core_message_features.cpp
index 3e8abf4..f8c3dce 100644
--- a/oemcrypto/odk/src/core_message_features.cpp
+++ b/oemcrypto/odk/src/core_message_features.cpp
@@ -4,20 +4,33 @@
#include "core_message_features.h"
+#include
+
+#include
#include
+#include
+#include
+
+#include "odk_structs.h"
namespace oemcrypto_core_message {
namespace features {
+namespace {
+// The first major version where we decided to prerelease a test version the ODK
+// library.
+constexpr int kFirstPrereleaseVersion = 20;
+} // namespace
+
const CoreMessageFeatures CoreMessageFeatures::kDefaultFeatures;
-bool CoreMessageFeatures::operator==(const CoreMessageFeatures &other) const {
+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;
+ uint32_t maximum_major_version, bool serve_prerelease_odk_messages) {
+ CoreMessageFeatures features(serve_prerelease_odk_messages);
features.maximum_major_version = maximum_major_version;
// The default minor version is the highest for each major version. This also
// needs to be updated with new version releases in
@@ -33,7 +46,10 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
features.maximum_minor_version = 4; // 18.4
break;
case 19:
- features.maximum_minor_version = 5; // 19.5
+ features.maximum_minor_version = 2; // 19.2
+ break;
+ case 20:
+ features.maximum_minor_version = 0; // 20.0
break;
default:
features.maximum_minor_version = 0;
@@ -41,8 +57,74 @@ CoreMessageFeatures CoreMessageFeatures::DefaultFeatures(
return features;
}
-std::ostream &operator<<(std::ostream &os,
- const CoreMessageFeatures &features) {
+CoreMessageFeatures::CoreMessageFeatures(bool prerelease_odk_messages)
+ : serve_prerelease_odk_messages(prerelease_odk_messages) {
+ if (prerelease_odk_messages) {
+ // If we are allowed to serve prerelease messages, then the maximum version
+ // is the same as the defined constants.
+ maximum_major_version = ODK_MAJOR_VERSION;
+ maximum_minor_version = ODK_MINOR_VERSION;
+ }
+}
+
+// Validate request version.
+bool CoreMessageFeatures::ValidateRequestVersion(uint16_t major_version,
+ uint16_t minor_version) const {
+ // First, make sure that this object has valid values. I.e. the maximum is not
+ // a version from the future.
+ if ((maximum_major_version > ODK_MAJOR_VERSION) ||
+ (maximum_major_version == ODK_MAJOR_VERSION &&
+ maximum_minor_version > ODK_MINOR_VERSION)) {
+ // TODO(b/147513335): this should be logged.
+ return false;
+ }
+ if (major_version < ODK_FIRST_VERSION) return false;
+ // If we are not allowed to serve messages to a prerelease device, then check
+ // to see if the request has a prerelease version number.
+ // Minor version of 0 indicates prerelease.
+ if (minor_version == 0 && !serve_prerelease_odk_messages) {
+ // if (major_version < kFirstPrereleaseVersion) Older devices are OK. There
+ // were no prerelease devices before kFirstPrereleaseVersion.
+ if (major_version < kFirstPrereleaseVersion) {
+ return true;
+ }
+
+ // If (major_version > ODK_MAJOR_VERSION), then the device is newer than the
+ // server. That happens when we are testing a prerelease device against a
+ // special test server that is explicitly for backwards compatibility
+ // testing. Since we want to allow prerelease devices to be tested for
+ // bacwards compatibility, we allow devices that are newer than the server.
+ //
+ // The UAT server, used for release validation testing, will be
+ // running recent software. The main reason to reject a prerelease device is
+ // to prevent a device from passing GTS tests with prerelease software. This
+ // statement assumes that UAT is updated quarterly, and that a prerelease
+ // ODK library will not be created in less than a few quarters after a major
+ // release.
+ if (major_version > ODK_MAJOR_VERSION) {
+ return true;
+ }
+ // All other prerelease devices are rejected.
+ return false;
+ }
+ return true;
+}
+
+bool CoreMessageFeatures::GetResponseVersion(
+ uint16_t request_major_version, uint16_t request_minor_version,
+ uint16_t& response_major_version, uint16_t& response_minor_version) const {
+ if (!ValidateRequestVersion(request_major_version, request_minor_version)) {
+ return false;
+ }
+ std::tie(response_major_version, response_minor_version) =
+ std::min(std::pair(request_major_version, request_minor_version),
+ std::pair(static_cast(maximum_major_version),
+ static_cast(maximum_minor_version)));
+ return true;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const CoreMessageFeatures& features) {
return os << "v" << features.maximum_major_version << "."
<< features.maximum_minor_version;
}
diff --git a/oemcrypto/odk/src/core_message_serialize.cpp b/oemcrypto/odk/src/core_message_serialize.cpp
index 888b957..b56df71 100644
--- a/oemcrypto/odk/src/core_message_serialize.cpp
+++ b/oemcrypto/odk/src/core_message_serialize.cpp
@@ -11,6 +11,7 @@
#include
#include "core_message_types.h"
+#include "odk_message.h"
#include "odk_serialize.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
@@ -33,33 +34,16 @@ bool CreateResponseHeader(const CoreMessageFeatures& features,
ODK_MessageType message_type,
ODK_CoreMessage* response_header,
const S& core_request) {
- // 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)) {
+ if (!features.GetResponseVersion(
+ core_request.api_major_version, core_request.api_minor_version,
+ response_header->nonce_values.api_major_version,
+ response_header->nonce_values.api_minor_version)) {
// TODO(b/147513335): this should be logged.
return false;
}
-
response_header->message_type = message_type;
- response_header->nonce_values.api_major_version =
- core_request.api_major_version;
- response_header->nonce_values.api_minor_version =
- core_request.api_minor_version;
response_header->nonce_values.nonce = core_request.nonce;
response_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) {
- response_header->nonce_values.api_major_version =
- features.maximum_major_version;
- response_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) {
- response_header->nonce_values.api_minor_version =
- features.maximum_minor_version;
- }
return true;
}
@@ -86,12 +70,13 @@ bool CreateResponse(ODK_MessageType message_type,
static constexpr size_t BUF_CAPACITY = 2048;
std::vector buf(BUF_CAPACITY, 0);
- ODK_Message msg = ODK_Message_Create(buf.data(), buf.capacity());
+ ODK_Message msg = ODK_Message_Create(buf.data(), buf.size());
packer(&msg, &response);
if (!ODK_Message_IsValid(&msg)) {
return false;
}
+ // Inserting message_length at the beginning of the buffer.
uint32_t message_length = static_cast(ODK_Message_GetSize(&msg));
msg = ODK_Message_Create(buf.data() + sizeof(response_header->message_type),
sizeof(response_header->message_length));
@@ -140,11 +125,7 @@ bool CreateCoreLicenseResponse(const CoreMessageFeatures& features,
bool CreateCoreReleaseResponse(const CoreMessageFeatures& features,
const ODK_ReleaseRequest& core_request,
- int64_t seconds_since_license_requested,
- int64_t seconds_since_first_decrypt,
std::string* oemcrypto_core_message) {
- (void)seconds_since_license_requested;
- (void)seconds_since_first_decrypt;
ODK_ReleaseResponse release_response{};
if (!CreateResponseHeader(features, ODK_Release_Response_Type,
&release_response.core_message, core_request)) {
diff --git a/oemcrypto/odk/src/core_message_serialize_proto.cpp b/oemcrypto/odk/src/core_message_serialize_proto.cpp
index edb9453..de2d32d 100644
--- a/oemcrypto/odk/src/core_message_serialize_proto.cpp
+++ b/oemcrypto/odk/src/core_message_serialize_proto.cpp
@@ -4,7 +4,6 @@
#include "core_message_serialize_proto.h"
-#include
#include
#include
#include
@@ -13,12 +12,11 @@
#include
#include "OEMCryptoCENCCommon.h"
+#include "core_message_features.h"
#include "core_message_serialize.h"
+#include "core_message_types.h"
#include "license_protocol.pb.h"
-#include "odk_serialize.h"
#include "odk_structs.h"
-#include "odk_structs_priv.h"
-#include "serialization_base.h"
namespace oemcrypto_core_message {
namespace serialize {
@@ -36,18 +34,17 @@ using oemcrypto_core_message::features::CoreMessageFeatures;
*/
OEMCrypto_Substring GetOecSubstring(std::string_view message,
std::string_view field) {
- OEMCrypto_Substring substring = {};
- size_t pos = message.find(field);
- if (pos != std::string::npos) {
- substring = OEMCrypto_Substring{pos, field.length()};
+ const size_t pos = message.find(field);
+ if (pos == std::string::npos) {
+ return OEMCrypto_Substring{0, 0};
}
- return substring;
+ return OEMCrypto_Substring{pos, field.length()};
}
-OEMCrypto_KeyObject KeyContainerToOecKey(
+OEMCrypto_KeyObjectV2 KeyContainerToOecKey(
std::string_view proto, const video_widevine::License::KeyContainer& k,
const bool uses_padding) {
- OEMCrypto_KeyObject obj = {};
+ OEMCrypto_KeyObjectV2 obj = {};
obj.key_id = GetOecSubstring(proto, k.id());
obj.key_data_iv = GetOecSubstring(proto, k.iv());
@@ -67,6 +64,48 @@ OEMCrypto_KeyObject KeyContainerToOecKey(
obj.key_control_iv = GetOecSubstring(proto, key_control.iv());
obj.key_control = GetOecSubstring(proto, key_control.key_control_block());
}
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_None;
+ memset(&(obj.decenc_mitigation_info.configuration_options), 0,
+ sizeof(obj.decenc_mitigation_info.configuration_options));
+ if (k.has_decenc_mitigation()) {
+ switch (k.decenc_mitigation().mitigation_option()) {
+ case video_widevine::License::KeyContainer::DecencMitigation::
+ DECENC_MITIGATION_OPTION_NONE:
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_None;
+ break;
+ case video_widevine::License::KeyContainer::DecencMitigation::
+ DECENC_MITIGATION_OPTION_AUTHENTICATE_BITSTREAM:
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream;
+ // Set the authentication key info for Authenticate Bitstream option.
+ obj.decenc_mitigation_info.configuration_options.authentication_key_info
+ .authentication_key =
+ GetOecSubstring(proto, k.decenc_mitigation()
+ .authenticate_bitstream_config_option()
+ .authentication_key());
+ obj.decenc_mitigation_info.configuration_options.authentication_key_info
+ .authentication_key_iv =
+ GetOecSubstring(proto, k.decenc_mitigation()
+ .authenticate_bitstream_config_option()
+ .authentication_key_iv());
+ break;
+ case video_widevine::License::KeyContainer::DecencMitigation::
+ DECENC_MITIGATION_OPTION_VALIDATE_BITSTREAM:
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream;
+ break;
+ case video_widevine::License::KeyContainer::DecencMitigation::
+ DECENC_MITIGATION_OPTION_RESTRICT_DECODING:
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding;
+ break;
+ default:
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_None;
+ }
+ }
return obj;
}
@@ -87,9 +126,10 @@ bool CreateCoreLicenseResponseFromProto(const CoreMessageFeatures& features,
}
ODK_Packing_ParsedLicense parsed_lic{};
- std::vector key_array;
+ std::vector key_array;
bool any_content = false;
bool any_entitlement = false;
+ bool any_decenc_mitigation = false;
for (int i = 0; i < lic.key_size(); ++i) {
const auto& k = lic.key(i);
@@ -116,6 +156,12 @@ bool CreateCoreLicenseResponseFromProto(const CoreMessageFeatures& features,
}
key_array.push_back(
KeyContainerToOecKey(serialized_license, k, uses_padding));
+ if (k.has_decenc_mitigation() &&
+ k.decenc_mitigation().mitigation_option() !=
+ video_widevine::License::KeyContainer::DecencMitigation::
+ DECENC_MITIGATION_OPTION_NONE) {
+ any_decenc_mitigation = true;
+ }
break;
}
default: {
@@ -149,15 +195,15 @@ bool CreateCoreLicenseResponseFromProto(const CoreMessageFeatures& features,
const auto& policy = lic.policy();
switch (policy.initial_renewal_delay_base()) {
case video_widevine::License_Policy::LICENSE_LOAD:
- parsed_lic.renewal_delay_base = OEMCrypto_License_Load;
+ parsed_lic.renewal_delay_base = OEMCrypto_LicenseLoad;
break;
case video_widevine::License_Policy::FIRST_DECRYPT:
- parsed_lic.renewal_delay_base = OEMCrypto_First_Decrypt;
+ parsed_lic.renewal_delay_base = OEMCrypto_FirstDecrypt;
break;
case video_widevine::License_Policy::TIMER_DELAY_BASE_UNSPECIFIED:
case video_widevine::License_Policy::LICENSE_START:
default:
- parsed_lic.renewal_delay_base = OEMCrypto_License_Start;
+ parsed_lic.renewal_delay_base = OEMCrypto_LicenseStart;
break;
}
ODK_TimerLimits& timer_limits = parsed_lic.timer_limits;
@@ -180,7 +226,10 @@ bool CreateCoreLicenseResponseFromProto(const CoreMessageFeatures& features,
parsed_lic.key_array = key_array.data();
parsed_lic.key_array_length = static_cast(key_array.size());
-
+ // If DeCENC mitigation option is used in any key, then set
+ // |decenc_mitigation_option_used| to a non-zero value. Otherwise, set the
+ // value to 0.
+ parsed_lic.decenc_mitigation_option_used = any_decenc_mitigation;
return CreateCoreLicenseResponse(features, parsed_lic, core_request,
core_request_sha256, oemcrypto_core_message);
}
diff --git a/oemcrypto/odk/src/odk.c b/oemcrypto/odk/src/odk.c
index 3f4090f..0d19968 100644
--- a/oemcrypto/odk/src/odk.c
+++ b/oemcrypto/odk/src/odk.c
@@ -38,9 +38,9 @@ static OEMCryptoResult ODK_PrepareRequest(
}
ODK_CoreMessage* core_message = (ODK_CoreMessage*)prepared_request_buffer;
*core_message = (ODK_CoreMessage){
- message_type,
- 0,
- *nonce_values,
+ .message_type = message_type,
+ .message_length = 0,
+ .nonce_values = *nonce_values,
};
/* Set core message length, and pack prepared request into message if the
@@ -145,13 +145,12 @@ static OEMCryptoResult ODK_PrepareRequest(
}
/* Parse the core message and verify that it has the right type. The nonce
- * values are updated to hold the response's API version.
+ * values are updated to hold the response's API version. This is used to
+ * parse a response, not a request.
*/
-static OEMCryptoResult ODK_ParseCoreHeader(const uint8_t* message,
- size_t message_length,
- size_t core_message_length,
- ODK_MessageType message_type,
- ODK_NonceValues* nonce_values) {
+static OEMCryptoResult ODK_ParseCoreHeaderInResponse(
+ const uint8_t* message, size_t 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) {
@@ -183,7 +182,7 @@ static OEMCryptoResult ODK_ParseCoreHeader(const uint8_t* message,
core_message.nonce_values.api_major_version < ODK_FIRST_VERSION) {
return ODK_UNSUPPORTED_API;
}
- if (nonce_values) {
+ if (nonce_values != NULL) {
/* If the server sent us an older format, record the message's API version.
*/
if (nonce_values->api_major_version >
@@ -213,15 +212,23 @@ static OEMCryptoResult ODK_ParseCoreHeader(const uint8_t* message,
OEMCryptoResult ODK_PrepareCoreLicenseRequest(
uint8_t* message, size_t message_length, size_t* core_message_size,
const ODK_NonceValues* nonce_values,
- const ODK_MessageCounterInfo* counter_info) {
+ const ODK_MessageCounterInfo* counter_info,
+ uint16_t decenc_mitigation_options_supported) {
if (core_message_size == NULL || nonce_values == NULL ||
counter_info == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
if (nonce_values->api_major_version > 17) {
- ODK_PreparedLicenseRequest license_request = {0};
- memcpy(&license_request.counter_info, counter_info,
- sizeof(license_request.counter_info));
+ if (!ODK_VersionSupportsDecencMitigation(nonce_values->api_major_version,
+ nonce_values->api_minor_version)) {
+ // |decenc_mitigation_options_supported| will be set to 0 if the version
+ // does not support decenc mitigation.
+ decenc_mitigation_options_supported = 0;
+ }
+ ODK_PreparedLicenseRequest license_request = {
+ .counter_info = *counter_info,
+ .decenc_mitigation_options_supported =
+ decenc_mitigation_options_supported};
return ODK_PrepareRequest(
message, message_length, core_message_size, ODK_License_Request_Type,
nonce_values, &license_request, sizeof(ODK_PreparedLicenseRequest));
@@ -235,25 +242,31 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
OEMCryptoResult ODK_PrepareCoreReleaseRequest(
uint8_t* message, size_t message_length, size_t* core_message_size,
- ODK_NonceValues* nonce_values, uint32_t status,
- uint32_t clock_security_level, int64_t seconds_since_license_requested,
- int64_t seconds_since_first_decrypt, ODK_ClockValues* clock_values,
- uint64_t system_time_seconds) {
- (void)status;
- (void)clock_security_level;
- (void)seconds_since_license_requested;
- (void)seconds_since_first_decrypt;
- if (core_message_size == NULL || nonce_values == NULL ||
+ ODK_NonceValues* nonce_values,
+ OEMCrypto_UsageEntryStatus usage_entry_status,
+ uint32_t clock_security_level, uint64_t seconds_since_license_requested,
+ uint64_t seconds_since_first_decrypt, const uint8_t* pst, size_t pst_length,
+ ODK_ClockValues* clock_values, uint64_t system_time_seconds) {
+ if (core_message_size == NULL || nonce_values == NULL || pst == NULL ||
clock_values == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
- if (nonce_values->api_major_version >= 19) {
- ODK_PreparedReleaseRequest release_request = {0};
+ if (nonce_values->api_major_version >= 20) {
+ // License release is only supported in API version 20 and above.
+ ODK_PreparedReleaseRequest release_request = {
+ .usage_entry_status = usage_entry_status,
+ .clock_security_level = clock_security_level,
+ .seconds_since_license_requested = seconds_since_license_requested,
+ .seconds_since_first_decrypt = seconds_since_first_decrypt,
+ .pst_length = (uint32_t)pst_length,
+ };
+ memset(release_request.pst, 0, sizeof(release_request.pst));
+ memcpy(release_request.pst, pst, pst_length);
return ODK_PrepareRequest(
message, message_length, core_message_size, ODK_Release_Request_Type,
nonce_values, &release_request, sizeof(ODK_PreparedReleaseRequest));
} else {
- // If the version is pre 19 when license release isn't supported, create a
+ // If the version is pre 20 when license release isn't supported, create a
// license request.
return ODK_PrepareCoreRenewalRequest(message, message_length,
core_message_size, nonce_values,
@@ -318,9 +331,8 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
return ODK_ERROR_CORE_MESSAGE;
}
if (nonce_values->api_major_version > 17) {
- ODK_PreparedProvisioningRequest provisioning_request = {0};
- memcpy(&provisioning_request.counter_info, counter_info,
- sizeof(ODK_MessageCounterInfo));
+ ODK_PreparedProvisioningRequest provisioning_request = {.counter_info =
+ *counter_info};
return ODK_PrepareRequest(message, message_length, core_message_length,
ODK_Provisioning_Request_Type, nonce_values,
@@ -343,16 +355,15 @@ OEMCryptoResult ODK_PrepareCoreProvisioning40Request(
counter_info == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
- ODK_PreparedProvisioning40Request provisioning_request = {0};
+ ODK_PreparedProvisioning40Request provisioning_request = {
+ .counter_info = *counter_info,
+ .device_info_length = (uint32_t)device_info_length};
if (device_info_length > sizeof(provisioning_request.device_info)) {
return ODK_ERROR_CORE_MESSAGE;
}
- provisioning_request.device_info_length = (uint32_t)device_info_length;
- if (device_info) {
+ if (device_info != NULL && device_info_length > 0) {
memcpy(provisioning_request.device_info, device_info, device_info_length);
}
- memcpy(&provisioning_request.counter_info, counter_info,
- sizeof(provisioning_request.counter_info));
return ODK_PrepareRequest(message, message_length, core_message_length,
ODK_Provisioning40_Request_Type, nonce_values,
@@ -368,20 +379,20 @@ OEMCryptoResult ODK_PrepareCoreRenewedProvisioningRequest(
if (core_message_length == NULL || nonce_values == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
- ODK_PreparedRenewedProvisioningRequest provisioning_request = {0};
+ ODK_PreparedRenewedProvisioningRequest provisioning_request = {
+ .device_id_length = (uint32_t)device_id_length,
+ .renewal_type = renewal_type,
+ .renewal_data_length = (uint32_t)renewal_data_length};
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) {
+ if (device_id != NULL && device_id_length > 0) {
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) {
+ if (renewal_data != NULL && renewal_data_length > 0) {
memcpy(provisioning_request.renewal_data, renewal_data,
renewal_data_length);
}
@@ -404,20 +415,18 @@ OEMCryptoResult ODK_ParseLicense(
return ODK_ERROR_CORE_MESSAGE;
}
- OEMCryptoResult err =
- ODK_ParseCoreHeader(message, message_length, core_message_length,
- ODK_License_Response_Type, nonce_values);
+ const OEMCryptoResult err = ODK_ParseCoreHeaderInResponse(
+ message, message_length, core_message_length, ODK_License_Response_Type,
+ nonce_values);
if (err != OEMCrypto_SUCCESS) {
return err;
}
- ODK_LicenseResponse license_response = {0};
- license_response.parsed_license = parsed_license;
-
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
-
ODK_Message_SetSize(&msg, core_message_length);
+ ODK_LicenseResponse license_response = {.parsed_license = parsed_license};
+
Unpack_ODK_LicenseResponse(&msg, &license_response);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
@@ -456,15 +465,14 @@ OEMCryptoResult ODK_ParseLicense(
clock_values->time_of_license_request_signed = system_time_seconds;
}
}
- bool license_load =
- (parsed_license->renewal_delay_base == OEMCrypto_License_Load);
+ const bool license_load =
+ (parsed_license->renewal_delay_base == OEMCrypto_LicenseLoad);
*timer_limits = parsed_license->timer_limits;
/* And update the clock values state. */
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
if (nonce_values->api_major_version >= 18 && license_load) {
- err = ODK_AttemptFirstPlayback(system_time_seconds, timer_limits,
- clock_values, timer_value);
- return err;
+ return ODK_AttemptFirstPlayback(system_time_seconds, timer_limits,
+ clock_values, timer_value);
}
return OEMCrypto_SUCCESS;
}
@@ -481,15 +489,16 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
return ODK_ERROR_CORE_MESSAGE;
}
- const OEMCryptoResult err =
- ODK_ParseCoreHeader(message, message_length, core_message_length,
- ODK_Renewal_Response_Type, nonce_values);
+ const OEMCryptoResult err = ODK_ParseCoreHeaderInResponse(
+ message, message_length, core_message_length, ODK_Renewal_Response_Type,
+ nonce_values);
if (err != OEMCrypto_SUCCESS) {
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);
+
+ ODK_RenewalResponse renewal_response = {0};
Unpack_ODK_RenewalResponse(&msg, &renewal_response);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
@@ -533,16 +542,17 @@ OEMCryptoResult ODK_ParseRelease(const uint8_t* message, size_t message_length,
return ODK_ERROR_CORE_MESSAGE;
}
- const OEMCryptoResult err =
- ODK_ParseCoreHeader(message, message_length, core_message_length,
- ODK_Release_Response_Type, nonce_values);
+ const OEMCryptoResult err = ODK_ParseCoreHeaderInResponse(
+ message, message_length, core_message_length, ODK_Release_Response_Type,
+ nonce_values);
if (err != OEMCrypto_SUCCESS) {
return err;
}
- ODK_ReleaseResponse release_response = {0};
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
ODK_Message_SetSize(&msg, core_message_length);
+
+ ODK_ReleaseResponse release_response = {0};
Unpack_ODK_ReleaseResponse(&msg, &release_response);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
@@ -561,24 +571,24 @@ OEMCryptoResult ODK_ParseProvisioning(
parsed_response == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
- const OEMCryptoResult err =
- ODK_ParseCoreHeader(message, message_length, core_message_length,
- ODK_Provisioning_Response_Type, nonce_values);
+ const OEMCryptoResult err = ODK_ParseCoreHeaderInResponse(
+ message, message_length, core_message_length,
+ ODK_Provisioning_Response_Type, nonce_values);
if (err != OEMCrypto_SUCCESS) {
return err;
}
if (nonce_values->api_major_version <= 17) {
// Do v16/v17
- ODK_ProvisioningResponseV16 provisioning_response = {0};
- provisioning_response.parsed_provisioning = parsed_response;
-
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
return ODK_ERROR_CORE_MESSAGE;
}
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
ODK_Message_SetSize(&msg, core_message_length);
+
+ ODK_ProvisioningResponseV16 provisioning_response = {.parsed_provisioning =
+ parsed_response};
Unpack_ODK_ProvisioningResponseV16(&msg, &provisioning_response);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
ODK_Message_GetOffset(&msg) != core_message_length) {
@@ -597,11 +607,11 @@ OEMCryptoResult ODK_ParseProvisioning(
}
} else {
// v18
- ODK_ProvisioningResponse provisioning_response = {0};
- provisioning_response.parsed_provisioning = parsed_response;
-
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
ODK_Message_SetSize(&msg, core_message_length);
+
+ ODK_ProvisioningResponse provisioning_response = {0};
+ provisioning_response.parsed_provisioning = parsed_response;
Unpack_ODK_ProvisioningResponse(&msg, &provisioning_response);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
ODK_Message_GetOffset(&msg) != core_message_length) {
@@ -624,16 +634,17 @@ OEMCryptoResult ODK_ParseProvisioning40(const uint8_t* message,
if (message == NULL || nonce_values == NULL) {
return ODK_ERROR_CORE_MESSAGE;
}
- const OEMCryptoResult err =
- ODK_ParseCoreHeader(message, message_length, core_message_length,
- ODK_Provisioning_Response_Type, nonce_values);
+ const OEMCryptoResult err = ODK_ParseCoreHeaderInResponse(
+ message, message_length, core_message_length,
+ ODK_Provisioning_Response_Type, nonce_values);
if (err != OEMCrypto_SUCCESS) {
return err;
}
- ODK_Provisioning40Response provisioning_response = {0};
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
ODK_Message_SetSize(&msg, core_message_length);
+
+ ODK_Provisioning40Response provisioning_response = {0};
Unpack_ODK_Provisioning40Response(&msg, &provisioning_response);
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
ODK_Message_GetOffset(&msg) != core_message_length) {
@@ -655,13 +666,16 @@ bool CheckApiVersionAtMost(const ODK_NonceValues* nonce_values,
nonce_values->api_minor_version <= minor_version);
}
+// These constants are exposed in the header file.
const uint8_t ODK_MacKeyLabelWithZero[] = "AUTHENTICATION";
+// Inclusion of null terminator is intentional.
const size_t ODK_MacKeyLabelWithZeroLength = sizeof(ODK_MacKeyLabelWithZero);
// This is the key size (512) in network byte order.
const uint8_t ODK_MacKeySuffix[] = {0x00, 0x00, 0x02, 0x00};
const size_t ODK_MacKeySuffixLength = sizeof(ODK_MacKeySuffix);
const uint8_t ODK_EncKeyLabelWithZero[] = "ENCRYPTION";
+// Inclusion of null terminator is intentional.
const size_t ODK_EncKeyLabelWithZeroLength = sizeof(ODK_EncKeyLabelWithZero);
// This is the key size (128) in network byte order.
const uint8_t ODK_EncKeySuffix[] = {0x00, 0x00, 0x00, 0x80};
@@ -673,34 +687,40 @@ OEMCryptoResult ODK_GenerateKeyContexts(const uint8_t* context,
size_t* mac_key_context_length,
uint8_t* enc_key_context,
size_t* enc_key_context_length) {
- size_t real_mac_length;
- size_t real_enc_length;
+ size_t real_mac_length = 0;
+ size_t real_enc_length = 0;
if (odk_add_overflow_ux(
context_length,
ODK_MacKeyLabelWithZeroLength + ODK_MacKeySuffixLength,
&real_mac_length) ||
- real_mac_length > 0xffffffff ||
+ real_mac_length > UINT32_MAX ||
odk_add_overflow_ux(
context_length,
ODK_EncKeyLabelWithZeroLength + ODK_EncKeySuffixLength,
&real_enc_length) ||
- real_enc_length > 0xffffffff) {
+ real_enc_length > UINT32_MAX) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
+ // Compute lengths for both key contexts before returning
+ // OEMCrypto_ERROR_SHORT_BUFFER.
bool short_buffer = false;
- if (mac_key_context_length) {
+ if (mac_key_context_length != NULL) {
short_buffer = real_mac_length > *mac_key_context_length;
*mac_key_context_length = real_mac_length;
}
- if (enc_key_context_length) {
+ if (enc_key_context_length != NULL) {
short_buffer = short_buffer || real_enc_length > *enc_key_context_length;
*enc_key_context_length = real_enc_length;
}
- if (short_buffer || !mac_key_context || !enc_key_context) {
+ if (short_buffer || mac_key_context == NULL || enc_key_context == NULL) {
return OEMCrypto_ERROR_SHORT_BUFFER;
}
- if (!context || !mac_key_context_length || !enc_key_context_length) {
+ // Returning OEMCrypto_ERROR_INVALID_CONTEXT here to allow for
+ // obtaining at least one of the correct lengths in the case of
+ // OEMCrypto_ERROR_SHORT_BUFFER.
+ if (context == NULL || mac_key_context_length == NULL ||
+ enc_key_context_length == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
diff --git a/oemcrypto/odk/src/odk_message_priv.h b/oemcrypto/odk/src/odk_message_priv.h
index f8e9bcc..74d8a59 100644
--- a/oemcrypto/odk/src/odk_message_priv.h
+++ b/oemcrypto/odk/src/odk_message_priv.h
@@ -5,10 +5,6 @@
#ifndef WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_
#define WIDEVINE_ODK_SRC_ODK_MESSAGE_PRIV_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/*
* This file must only be included by odk_message.c and serialization_base.c.
*/
@@ -18,6 +14,10 @@ extern "C" {
#include "odk_message.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* This is the implementation of a message. This structure is private, i.e. it
* should only be included by files that are allowed to modify the internals of
diff --git a/oemcrypto/odk/src/odk_overflow.c b/oemcrypto/odk/src/odk_overflow.c
index ba19962..4ffd1f8 100644
--- a/oemcrypto/odk/src/odk_overflow.c
+++ b/oemcrypto/odk/src/odk_overflow.c
@@ -1,48 +1,42 @@
// Copyright 2019 Google LLC. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
-
#include "odk_overflow.h"
#include
#include
+#define NO_OVERFLOW 0
+#define OVERFLOW_ERROR 1
+
int odk_sub_overflow_u64(uint64_t a, uint64_t b, uint64_t* c) {
- if (a >= b) {
- if (c) {
- *c = a - b;
- }
- return 0;
+ if (a < b) return OVERFLOW_ERROR;
+ if (c != NULL) {
+ *c = a - b;
}
- return 1;
+ return NO_OVERFLOW;
}
int odk_add_overflow_u64(uint64_t a, uint64_t b, uint64_t* c) {
- if (UINT64_MAX - a >= b) {
- if (c) {
- *c = a + b;
- }
- return 0;
+ if ((UINT64_MAX - a) < b) return OVERFLOW_ERROR;
+ if (c != NULL) {
+ *c = a + b;
}
- return 1;
+ return NO_OVERFLOW;
}
int odk_add_overflow_ux(size_t a, size_t b, size_t* c) {
- if (SIZE_MAX - a >= b) {
- if (c) {
- *c = a + b;
- }
- return 0;
+ if ((SIZE_MAX - a) < b) return OVERFLOW_ERROR;
+ if (c != NULL) {
+ *c = a + b;
}
- return 1;
+ return NO_OVERFLOW;
}
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) {
+ if (b > 0 && a > (SIZE_MAX / b)) return OVERFLOW_ERROR;
+ if (c != NULL) {
*c = a * b;
}
- return 0;
+ return NO_OVERFLOW;
}
diff --git a/oemcrypto/odk/src/odk_overflow.h b/oemcrypto/odk/src/odk_overflow.h
index 7b50552..835f05b 100644
--- a/oemcrypto/odk/src/odk_overflow.h
+++ b/oemcrypto/odk/src/odk_overflow.h
@@ -12,6 +12,12 @@
extern "C" {
#endif
+// ODK overflow-safe math functions.
+//
+// Performs an operation using the two operands |a| and |b|,
+// and assigns the result to |c| if not NULL.
+//
+// Returns 1 if an overflow occurred, 0 otherwise.
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_ux(size_t a, size_t b, size_t* c);
diff --git a/oemcrypto/odk/src/odk_serialize.c b/oemcrypto/odk/src/odk_serialize.c
index 1f2e48e..c9e1942 100644
--- a/oemcrypto/odk/src/odk_serialize.c
+++ b/oemcrypto/odk/src/odk_serialize.c
@@ -1,22 +1,37 @@
// Copyright 2019 Google LLC. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
-
-/*
- * This code is auto-generated, do not edit
- */
-
#include "odk_serialize.h"
+#include
+#include
+
+#include "OEMCryptoCENCCommon.h"
#include "odk_message.h"
#include "odk_overflow.h"
+#include "odk_structs.h"
#include "odk_structs_priv.h"
+#include "odk_target.h"
#include "serialization_base.h"
/* @ serialize */
/* @@ private serialize */
+bool ODK_VersionSupportsDecencMitigation(uint16_t api_major_version,
+ uint16_t api_minor_version) {
+ if (api_major_version >= 20) {
+ return true;
+ }
+ if (api_major_version == 19) {
+ return (api_minor_version >= 7);
+ }
+ if (api_major_version == 18) {
+ return (api_minor_version >= 11);
+ }
+ return false;
+}
+
static void Pack_ODK_NonceValues(ODK_Message* msg, ODK_NonceValues const* obj) {
Pack_uint16_t(msg, &obj->api_minor_version);
Pack_uint16_t(msg, &obj->api_major_version);
@@ -30,13 +45,44 @@ static void Pack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage const* obj) {
Pack_ODK_NonceValues(msg, &obj->nonce_values);
}
+static void Pack_OEMCrypto_Authentication_Key_Info(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo const* obj) {
+ Pack_OEMCrypto_Substring(msg, &obj->authentication_key);
+ Pack_OEMCrypto_Substring(msg, &obj->authentication_key_iv);
+}
+
+static void Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info const* obj) {
+ Pack_uint32_t(msg, &obj->mitigation_option);
+ if (obj->mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream) {
+ Pack_OEMCrypto_Authentication_Key_Info(
+ msg, &obj->configuration_options.authentication_key_info);
+ } else if (obj->mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream ||
+ obj->mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding) {
+ // These mitigation options do not require any additional data from the key
+ // object.
+ } else {
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ return;
+ }
+}
+
static void Pack_OEMCrypto_KeyObject(ODK_Message* msg,
- OEMCrypto_KeyObject const* obj) {
+ OEMCrypto_KeyObjectV2 const* obj,
+ size_t key_obj_version) {
Pack_OEMCrypto_Substring(msg, &obj->key_id);
Pack_OEMCrypto_Substring(msg, &obj->key_data_iv);
Pack_OEMCrypto_Substring(msg, &obj->key_data);
Pack_OEMCrypto_Substring(msg, &obj->key_control_iv);
Pack_OEMCrypto_Substring(msg, &obj->key_control);
+ if (key_obj_version >= 2) {
+ // For |key_obj_version| >= 2, the |decenc_mitigation_info| is expected,
+ // even if it is set to OEMCrypto_DeCENC_Mitigation_Option_None.
+ Pack_OEMCrypto_DeCENC_Mitigation_Info(msg, &obj->decenc_mitigation_info);
+ }
}
static void Pack_ODK_TimerLimits(ODK_Message* msg, ODK_TimerLimits const* obj) {
@@ -84,19 +130,43 @@ static void Pack_ODK_ParsedLicense(ODK_Message* msg,
if (nonce_values->api_major_version >= 18) {
Pack_enum(msg, obj->renewal_delay_base);
}
- 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]);
+ if (ODK_VersionSupportsDecencMitigation(nonce_values->api_major_version,
+ nonce_values->api_minor_version)) {
+ Pack_uint16_t(msg, &obj->decenc_mitigation_option_used);
+ } else if (obj->decenc_mitigation_option_used != 0) {
+ // Bad parameter, DeCENC not supported.
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_UNKNOWN_ERROR);
+ return;
+ } else {
+ static const uint16_t kDecencOptionNone = 0;
+ Pack_uint16_t(msg, &kDecencOptionNone);
+ }
+ Pack_uint16_t(msg, &obj->key_array_length);
+ for (uint32_t i = 0; i < obj->key_array_length; i++) {
+ if (obj->decenc_mitigation_option_used != 0) {
+ Pack_OEMCrypto_KeyObject(msg, &obj->key_array[i], 2);
+ } else {
+ Pack_OEMCrypto_KeyObject(msg, &obj->key_array[i], 1);
+ }
}
}
static void Pack_ODK_ParsedProvisioning(ODK_Message* msg,
- ODK_ParsedProvisioning const* obj) {
+ ODK_ParsedProvisioning const* obj,
+ const ODK_NonceValues* nonce_values) {
Pack_enum(msg, obj->key_type);
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key_iv);
Pack_OEMCrypto_Substring(msg, &obj->encrypted_message_key);
+ if (nonce_values->api_major_version >= 20) {
+ Pack_OEMCrypto_Substring(msg, &obj->curr_server_sealing_key);
+ Pack_uint32_t(msg, &obj->server_sealing_key_array_length);
+ for (uint32_t i = 0; i < obj->server_sealing_key_array_length &&
+ i < ODK_MAX_NUM_SERVER_SEALING_KEYS;
+ i++) {
+ Pack_OEMCrypto_Substring(msg, &obj->server_sealing_key_array[i]);
+ }
+ }
}
static void Pack_ODK_MessageCounterInfo(ODK_Message* msg,
@@ -119,6 +189,7 @@ void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
ODK_PreparedLicenseRequest const* obj) {
Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_ODK_MessageCounterInfo(msg, &obj->counter_info);
+ Pack_uint16_t(msg, &obj->decenc_mitigation_options_supported);
}
void Pack_ODK_PreparedLicenseRequestV17(
@@ -129,6 +200,16 @@ void Pack_ODK_PreparedLicenseRequestV17(
void Pack_ODK_PreparedReleaseRequest(ODK_Message* msg,
const ODK_PreparedReleaseRequest* obj) {
Pack_ODK_CoreMessage(msg, &obj->core_message);
+ Pack_uint32_t(msg, &obj->usage_entry_status);
+ Pack_uint32_t(msg, &obj->clock_security_level);
+ Pack_uint64_t(msg, &obj->seconds_since_license_requested);
+ Pack_uint64_t(msg, &obj->seconds_since_first_decrypt);
+ Pack_uint32_t(msg, &obj->pst_length);
+ if (obj->pst_length > ODK_PST_LEN_MAX) {
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
+ return;
+ }
+ PackFixedArray(msg, &obj->pst[0], obj->pst_length, ODK_PST_LEN_MAX);
}
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
@@ -142,7 +223,7 @@ void Pack_ODK_PreparedProvisioningRequest(
Pack_ODK_CoreMessage(msg, &obj->core_message);
// Fake device_id_length for older servers, since we removed device id from
// the v18 request
- uint32_t device_id_len = 64;
+ const uint32_t device_id_len = ODK_DEVICE_ID_LEN_MAX;
Pack_uint32_t(msg, &device_id_len);
Pack_ODK_MessageCounterInfo(msg, &obj->counter_info);
}
@@ -180,7 +261,7 @@ void Pack_ODK_LicenseResponse(ODK_Message* msg,
Pack_ODK_ParsedLicense(msg,
(const ODK_Packing_ParsedLicense*)obj->parsed_license,
&obj->core_message.nonce_values);
- if ((&obj->core_message.nonce_values)->api_major_version == 16) {
+ if (obj->core_message.nonce_values.api_major_version == 16) {
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
}
}
@@ -200,14 +281,16 @@ void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
const ODK_ProvisioningResponse* obj) {
Pack_ODK_CoreMessage(msg, &obj->core_message);
Pack_ODK_ParsedProvisioning(
- msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning);
+ msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning,
+ &obj->core_message.nonce_values);
}
void Pack_ODK_ProvisioningResponseV16(ODK_Message* msg,
const ODK_ProvisioningResponseV16* obj) {
Pack_ODK_PreparedProvisioningRequestV17(msg, &obj->request);
Pack_ODK_ParsedProvisioning(
- msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning);
+ msg, (const ODK_ParsedProvisioning*)obj->parsed_provisioning,
+ &obj->request.core_message.nonce_values);
}
void Pack_ODK_Provisioning40Response(ODK_Message* msg,
@@ -232,13 +315,47 @@ void Unpack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage* obj) {
Unpack_ODK_NonceValues(msg, &obj->nonce_values);
}
+static void Unpack_OEMCrypto_Authentication_Key_Info(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo* obj) {
+ Unpack_OEMCrypto_Substring(msg, &obj->authentication_key);
+ Unpack_OEMCrypto_Substring(msg, &obj->authentication_key_iv);
+}
+
+static void Unpack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info* obj) {
+ Unpack_uint32_t(msg, &obj->mitigation_option);
+ // Check that the mitigation_option only has 1 bit set or is 0.
+ if ((obj->mitigation_option & (obj->mitigation_option - 1)) != 0) {
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ return;
+ }
+ if (obj->mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream) {
+ Unpack_OEMCrypto_Authentication_Key_Info(
+ msg, &obj->configuration_options.authentication_key_info);
+ } else if (obj->mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream ||
+ obj->mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding) {
+ // These mitigation options do not require any additional data from the key
+ // object.
+ } else {
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ return;
+ }
+}
+
static void Unpack_OEMCrypto_KeyObject(ODK_Message* msg,
- OEMCrypto_KeyObject* obj) {
+ OEMCrypto_KeyObjectV2* obj,
+ size_t key_obj_version) {
Unpack_OEMCrypto_Substring(msg, &obj->key_id);
Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
Unpack_OEMCrypto_Substring(msg, &obj->key_data);
Unpack_OEMCrypto_Substring(msg, &obj->key_control_iv);
Unpack_OEMCrypto_Substring(msg, &obj->key_control);
+ if (key_obj_version >= 2) {
+ Unpack_OEMCrypto_DeCENC_Mitigation_Info(msg, &obj->decenc_mitigation_info);
+ }
/*
Edge case for servers that incorrectly process protocol VERSION_2_2 padding.
@@ -314,23 +431,44 @@ static void Unpack_ODK_ParsedLicense(ODK_Message* msg, ODK_ParsedLicense* obj,
if (nonce_values->api_major_version >= 18) {
Unpack_OEMCrypto_TimerDelayBase(msg, &obj->renewal_delay_base);
}
- Unpack_uint32_t(msg, &obj->key_array_length);
+ Unpack_uint16_t(msg, &obj->decenc_mitigation_option_used);
+ if (!ODK_VersionSupportsDecencMitigation(nonce_values->api_major_version,
+ nonce_values->api_minor_version) &&
+ obj->decenc_mitigation_option_used != 0) {
+ // Bad ODK message, DeCENC not supported.
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_UNKNOWN_ERROR);
+ return;
+ }
+ Unpack_uint16_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]);
+ for (uint32_t i = 0; i < obj->key_array_length; i++) {
+ if (obj->decenc_mitigation_option_used != 0) {
+ Unpack_OEMCrypto_KeyObject(msg, &obj->key_array[i], 2);
+ } else {
+ Unpack_OEMCrypto_KeyObject(msg, &obj->key_array[i], 1);
+ }
}
}
static void Unpack_ODK_ParsedProvisioning(ODK_Message* msg,
- ODK_ParsedProvisioning* obj) {
+ ODK_ParsedProvisioning* obj,
+ const ODK_NonceValues* nonce_values) {
Unpack_OEMCrypto_PrivateKeyType(msg, &obj->key_type);
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key_iv);
Unpack_OEMCrypto_Substring(msg, &obj->encrypted_message_key);
+ if (nonce_values->api_major_version >= 20) {
+ Unpack_OEMCrypto_Substring(msg, &obj->curr_server_sealing_key);
+ Unpack_uint32_t(msg, &obj->server_sealing_key_array_length);
+ for (uint32_t i = 0; i < obj->server_sealing_key_array_length &&
+ i < ODK_MAX_NUM_SERVER_SEALING_KEYS;
+ i++) {
+ Unpack_OEMCrypto_Substring(msg, &obj->server_sealing_key_array[i]);
+ }
+ }
}
static void Unpack_ODK_MessageCounterInfo(ODK_Message* msg,
@@ -353,6 +491,14 @@ void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
ODK_PreparedLicenseRequest* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_ODK_MessageCounterInfo(msg, &obj->counter_info);
+ // Check that there is enough space for the
+ // decenc_mitigation_options_supported field. Major and minor version checks
+ // will be added in the future.
+ if ((ODK_Message_GetSize(msg) - ODK_Message_GetOffset(msg)) >= 2) {
+ Unpack_uint16_t(msg, &obj->decenc_mitigation_options_supported);
+ } else {
+ obj->decenc_mitigation_options_supported = 0;
+ }
}
void Unpack_ODK_PreparedLicenseRequestV17(ODK_Message* msg,
@@ -363,6 +509,16 @@ void Unpack_ODK_PreparedLicenseRequestV17(ODK_Message* msg,
void Unpack_ODK_PreparedReleaseRequest(ODK_Message* msg,
ODK_PreparedReleaseRequest* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message);
+ Unpack_uint32_t(msg, &obj->usage_entry_status);
+ Unpack_uint32_t(msg, &obj->clock_security_level);
+ Unpack_uint64_t(msg, &obj->seconds_since_license_requested);
+ Unpack_uint64_t(msg, &obj->seconds_since_first_decrypt);
+ Unpack_uint32_t(msg, &obj->pst_length);
+ if (obj->pst_length > ODK_PST_LEN_MAX) {
+ ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
+ return;
+ }
+ UnpackFixedArray(msg, &obj->pst[0], obj->pst_length, ODK_PST_LEN_MAX);
}
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
@@ -422,7 +578,7 @@ void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message);
Unpack_ODK_ParsedLicense(msg, obj->parsed_license,
&obj->core_message.nonce_values);
- if ((&obj->core_message.nonce_values)->api_major_version == 16) {
+ if (obj->core_message.nonce_values.api_major_version == 16) {
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
}
}
@@ -439,13 +595,15 @@ void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj) {
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
ODK_ProvisioningResponse* obj) {
Unpack_ODK_CoreMessage(msg, &obj->core_message);
- Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
+ Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning,
+ &obj->core_message.nonce_values);
}
void Unpack_ODK_ProvisioningResponseV16(ODK_Message* msg,
ODK_ProvisioningResponseV16* obj) {
Unpack_ODK_PreparedProvisioningRequestV17(msg, &obj->request);
- Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
+ Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning,
+ &obj->request.core_message.nonce_values);
}
void Unpack_ODK_Provisioning40Response(ODK_Message* msg,
diff --git a/oemcrypto/odk/src/odk_serialize.h b/oemcrypto/odk/src/odk_serialize.h
index a7aa220..c1df9ae 100644
--- a/oemcrypto/odk/src/odk_serialize.h
+++ b/oemcrypto/odk/src/odk_serialize.h
@@ -8,6 +8,8 @@
#ifndef WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_
#define WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_
+#include
+
#include "odk_message.h"
#include "odk_structs_priv.h"
@@ -15,6 +17,9 @@
extern "C" {
#endif
+bool ODK_VersionSupportsDecencMitigation(uint16_t api_major_version,
+ uint16_t api_minor_version);
+
/* odk pack */
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
const ODK_PreparedLicenseRequest* obj);
diff --git a/oemcrypto/odk/src/odk_structs_priv.h b/oemcrypto/odk/src/odk_structs_priv.h
index 208ce2c..9bc0f87 100644
--- a/oemcrypto/odk/src/odk_structs_priv.h
+++ b/oemcrypto/odk/src/odk_structs_priv.h
@@ -43,6 +43,7 @@ typedef struct {
typedef struct {
ODK_CoreMessage core_message;
ODK_MessageCounterInfo counter_info;
+ uint16_t decenc_mitigation_options_supported;
} ODK_PreparedLicenseRequest;
typedef struct {
@@ -51,6 +52,12 @@ typedef struct {
typedef struct {
ODK_CoreMessage core_message;
+ OEMCrypto_UsageEntryStatus usage_entry_status;
+ uint32_t clock_security_level;
+ uint64_t seconds_since_license_requested;
+ uint64_t seconds_since_first_decrypt;
+ uint32_t pst_length;
+ uint8_t pst[ODK_PST_LEN_MAX];
} ODK_PreparedReleaseRequest;
typedef struct {
@@ -130,9 +137,9 @@ typedef struct {
// request structs change. Refer to test suite OdkSizeTest in
// ../test/odk_test.cpp for validations of each of the defined request sizes.
#define ODK_CORE_MESSAGE_SIZE 20u
-#define ODK_LICENSE_REQUEST_SIZE 90u
+#define ODK_LICENSE_REQUEST_SIZE 92u
#define ODK_LICENSE_REQUEST_SIZE_V17 20u
-#define ODK_RELEASE_REQUEST_SIZE 20u
+#define ODK_RELEASE_REQUEST_SIZE 304u
#define ODK_RENEWAL_REQUEST_SIZE 28u
#define ODK_PROVISIONING_REQUEST_SIZE 94u
#define ODK_PROVISIONING_REQUEST_SIZE_V17 88u
diff --git a/oemcrypto/odk/src/odk_timer.c b/oemcrypto/odk/src/odk_timer.c
index a1a9eb8..616cd11 100644
--- a/oemcrypto/odk/src/odk_timer.c
+++ b/oemcrypto/odk/src/odk_timer.c
@@ -5,9 +5,11 @@
#include
#include
+#include "OEMCryptoCENCCommon.h"
#include "odk.h"
#include "odk_attributes.h"
#include "odk_overflow.h"
+#include "odk_structs.h"
#include "odk_structs_priv.h"
/* Private function. Checks to see if the license is active. Returns
@@ -25,7 +27,7 @@ static OEMCryptoResult ODK_LicenseActive(const ODK_TimerLimits* timer_limits,
clock_values->timer_status == ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
- if (clock_values->status > kActive) {
+ if (clock_values->status > OEMCrypto_Active) {
return ODK_TIMER_EXPIRED;
}
return OEMCrypto_SUCCESS;
@@ -271,14 +273,17 @@ OEMCryptoResult ODK_InitializeSessionValues(ODK_TimerLimits* timer_limits,
nonce_values->api_minor_version = 5;
break;
case 17:
- nonce_values->api_minor_version = 2;
+ nonce_values->api_minor_version = 7;
break;
case 18:
- nonce_values->api_minor_version = 4;
+ nonce_values->api_minor_version = 9;
break;
case 19:
nonce_values->api_minor_version = 5;
break;
+ case ODK_MAJOR_VERSION:
+ nonce_values->api_minor_version = ODK_MINOR_VERSION;
+ break;
default:
nonce_values->api_minor_version = 0;
break;
@@ -316,7 +321,7 @@ OEMCryptoResult ODK_InitializeClockValues(ODK_ClockValues* clock_values,
clock_values->time_of_renewal_request = 0;
clock_values->time_when_timer_expires = 0;
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED;
- clock_values->status = kUnused;
+ clock_values->status = OEMCrypto_Unused;
return OEMCrypto_SUCCESS;
}
@@ -325,7 +330,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
uint64_t time_of_license_request_signed,
uint64_t time_of_first_decrypt,
uint64_t time_of_last_decrypt,
- enum OEMCrypto_Usage_Entry_Status status,
+ enum OEMCrypto_UsageEntryStatus status,
uint64_t system_time_seconds UNUSED) {
if (clock_values == NULL) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
@@ -389,7 +394,7 @@ OEMCryptoResult ODK_AttemptFirstPlayback(uint64_t system_time_seconds,
/* If playback has not already started, then this is the first playback. */
if (clock_values->time_of_first_decrypt == 0) {
clock_values->time_of_first_decrypt = system_time_seconds;
- clock_values->status = kActive;
+ clock_values->status = OEMCrypto_Active;
}
/* Similar to the rental window, we check the playback window
@@ -456,10 +461,10 @@ OEMCryptoResult ODK_DeactivateUsageEntry(ODK_ClockValues* clock_values) {
if (clock_values == NULL) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
- if (clock_values->status == kUnused) {
- clock_values->status = kInactiveUnused;
- } else if (clock_values->status == kActive) {
- clock_values->status = kInactiveUsed;
+ if (clock_values->status == OEMCrypto_Unused) {
+ clock_values->status = OEMCrypto_InactiveUnused;
+ } else if (clock_values->status == OEMCrypto_Active) {
+ clock_values->status = OEMCrypto_InactiveUsed;
}
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
return OEMCrypto_SUCCESS;
@@ -507,7 +512,7 @@ OEMCryptoResult ODK_RefreshV15Values(const ODK_TimerLimits* timer_limits,
if (nonce_values->api_major_version != 15) {
return OEMCrypto_ERROR_INVALID_NONCE;
}
- if (clock_values->status > kActive) {
+ if (clock_values->status > OEMCrypto_Active) {
clock_values->timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
return ODK_TIMER_EXPIRED;
}
diff --git a/oemcrypto/odk/src/odk_util.c b/oemcrypto/odk/src/odk_util.c
index 12c93e4..e9eccd5 100644
--- a/oemcrypto/odk/src/odk_util.c
+++ b/oemcrypto/odk/src/odk_util.c
@@ -4,6 +4,8 @@
#include "odk_util.h"
+#include "odk_structs.h"
+
int crypto_memcmp(const void* in_a, const void* in_b, size_t len) {
if (len == 0) {
return 0;
diff --git a/oemcrypto/odk/src/serialization_base.c b/oemcrypto/odk/src/serialization_base.c
index 4527b2a..80d06ff 100644
--- a/oemcrypto/odk/src/serialization_base.c
+++ b/oemcrypto/odk/src/serialization_base.c
@@ -27,70 +27,89 @@ static ODK_Message_Impl* GetMessageImpl(ODK_Message* message) {
static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
ODK_Message_Impl* message_impl = GetMessageImpl(message);
- if (!message_impl) return;
- if (count <= message_impl->capacity - message_impl->size) {
+ if (message_impl == NULL) return;
+ if (count > (message_impl->capacity - message_impl->size)) {
+ message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
+ return;
+ }
+ if (count > 0) {
+ assert(ptr);
memcpy((void*)(message_impl->base + message_impl->size), (const void*)ptr,
count);
message_impl->size += count;
- } else {
- message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
}
}
+static void PackPaddingBytes(ODK_Message* message, uint8_t fill_value,
+ size_t count) {
+ ODK_Message_Impl* message_impl = GetMessageImpl(message);
+ if (message_impl == NULL) return;
+ if (count > (message_impl->capacity - message_impl->size)) {
+ message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
+ return;
+ }
+ if (count == 0) return;
+ memset((void*)(message_impl->base + message_impl->size), fill_value, count);
+ message_impl->size += count;
+}
+
void Pack_enum(ODK_Message* message, int value) {
- uint32_t v32 = (uint32_t)value;
- Pack_uint32_t(message, &v32);
+ const uint32_t value_u32 = (uint32_t)value;
+ Pack_uint32_t(message, &value_u32);
}
void Pack_bool(ODK_Message* message, const bool* value) {
assert(value);
- uint8_t data[4] = {0};
- data[3] = *value ? 1 : 0;
+ const uint8_t data[4] = {0, 0, 0, *value ? 1 : 0};
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);
+ const uint8_t data[1] = {*value};
PackBytes(message, data, sizeof(data));
}
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
assert(value);
- uint8_t data[2] = {0};
- data[0] = (uint8_t)(*value >> 8);
- data[1] = (uint8_t)(*value >> 0);
+ const uint8_t data[2] = {(uint8_t)(*value >> 8), (uint8_t)(*value >> 0)};
PackBytes(message, data, sizeof(data));
}
void Pack_uint32_t(ODK_Message* message, const uint32_t* value) {
assert(value);
- uint8_t data[4] = {0};
- data[0] = (uint8_t)(*value >> 24);
- data[1] = (uint8_t)(*value >> 16);
- data[2] = (uint8_t)(*value >> 8);
- data[3] = (uint8_t)(*value >> 0);
+ const uint8_t data[4] = {(uint8_t)(*value >> 24), (uint8_t)(*value >> 16),
+ (uint8_t)(*value >> 8), (uint8_t)(*value >> 0)};
PackBytes(message, data, sizeof(data));
}
void Pack_uint64_t(ODK_Message* message, const uint64_t* value) {
assert(value);
- uint32_t hi = (uint32_t)(*value >> 32);
- uint32_t lo = (uint32_t)(*value);
- Pack_uint32_t(message, &hi);
- Pack_uint32_t(message, &lo);
+ const uint32_t high = (uint32_t)(*value >> 32);
+ const uint32_t low = (uint32_t)(*value);
+ Pack_uint32_t(message, &high);
+ Pack_uint32_t(message, &low);
}
void PackArray(ODK_Message* message, const uint8_t* base, size_t size) {
PackBytes(message, base, size);
}
+// Writes a total of |data_field_size| bytes.
+// The first |data_length| bytes are from |data|,
+// the next |data_field_size - data_length| bytes are zero 0.
+void PackFixedArray(ODK_Message* message, const uint8_t* data,
+ size_t data_length, size_t data_field_size) {
+ assert(data_length <= data_field_size);
+ PackBytes(message, data, data_length);
+ PackPaddingBytes(message, 0, data_field_size - data_length);
+}
+
void Pack_OEMCrypto_Substring(ODK_Message* message,
const OEMCrypto_Substring* obj) {
assert(obj);
- uint32_t offset = (uint32_t)obj->offset;
- uint32_t length = (uint32_t)obj->length;
+ const uint32_t offset = (uint32_t)obj->offset;
+ const uint32_t length = (uint32_t)obj->length;
Pack_uint32_t(message, &offset);
Pack_uint32_t(message, &length);
}
@@ -98,23 +117,36 @@ void Pack_OEMCrypto_Substring(ODK_Message* message,
static void UnpackBytes(ODK_Message* message, uint8_t* ptr, size_t count) {
assert(ptr);
ODK_Message_Impl* message_impl = GetMessageImpl(message);
- if (!message_impl) return;
- if (count <= message_impl->size - message_impl->read_offset) {
+ if (message_impl == NULL) return;
+ if (count > (message_impl->size - message_impl->read_offset)) {
+ message_impl->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
+ return;
+ }
+ if (count > 0) {
memcpy((void*)ptr, (void*)(message_impl->base + message_impl->read_offset),
count);
message_impl->read_offset += count;
- } else {
- message_impl->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
}
}
+static void SkipBytes(ODK_Message* message, size_t count) {
+ ODK_Message_Impl* message_impl = GetMessageImpl(message);
+ if (message_impl == NULL) return;
+ if (count > (message_impl->size - message_impl->read_offset)) {
+ message_impl->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
+ return;
+ }
+ if (count == 0) return;
+ message_impl->read_offset += count;
+}
+
void Unpack_OEMCrypto_LicenseType(ODK_Message* message,
OEMCrypto_LicenseType* value) {
assert(value);
- uint32_t v32 = 0;
- Unpack_uint32_t(message, &v32);
- if (v32 <= OEMCrypto_LicenseType_MaxValue) {
- *value = (OEMCrypto_LicenseType)v32;
+ uint32_t value_u32 = 0;
+ Unpack_uint32_t(message, &value_u32);
+ if (value_u32 <= OEMCrypto_LicenseType_MaxValue) {
+ *value = (OEMCrypto_LicenseType)value_u32;
} else {
ODK_Message_SetStatus(message, MESSAGE_STATUS_PARSE_ERROR);
}
@@ -123,10 +155,10 @@ void Unpack_OEMCrypto_LicenseType(ODK_Message* message,
void Unpack_OEMCrypto_PrivateKeyType(ODK_Message* message,
OEMCrypto_PrivateKeyType* value) {
assert(value);
- uint32_t v32 = 0;
- Unpack_uint32_t(message, &v32);
- if (v32 <= OEMCrypto_PrivateKeyType_MaxValue) {
- *value = (OEMCrypto_PrivateKeyType)v32;
+ uint32_t value_u32 = 0;
+ Unpack_uint32_t(message, &value_u32);
+ if (value_u32 <= OEMCrypto_PrivateKeyType_MaxValue) {
+ *value = (OEMCrypto_PrivateKeyType)value_u32;
} else {
ODK_Message_SetStatus(message, MESSAGE_STATUS_PARSE_ERROR);
}
@@ -135,10 +167,10 @@ void Unpack_OEMCrypto_PrivateKeyType(ODK_Message* message,
void Unpack_OEMCrypto_TimerDelayBase(ODK_Message* message,
OEMCrypto_TimerDelayBase* value) {
assert(value);
- uint32_t v32 = 0;
- Unpack_uint32_t(message, &v32);
- if (v32 <= OEMCrypto_TimerDelayBase_MaxValue) {
- *value = (OEMCrypto_TimerDelayBase)v32;
+ uint32_t value_u32 = 0;
+ Unpack_uint32_t(message, &value_u32);
+ if (value_u32 <= OEMCrypto_TimerDelayBase_MaxValue) {
+ *value = (OEMCrypto_TimerDelayBase)value_u32;
} else {
ODK_Message_SetStatus(message, MESSAGE_STATUS_PARSE_ERROR);
}
@@ -168,7 +200,7 @@ void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
- if (!message_impl) return;
+ if (message_impl == NULL) return;
uint8_t data[4] = {0};
UnpackBytes(message, data, sizeof(data));
assert(value);
@@ -179,22 +211,23 @@ void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
}
void Unpack_uint64_t(ODK_Message* message, uint64_t* value) {
- uint32_t hi = 0;
- uint32_t lo = 0;
- Unpack_uint32_t(message, &hi);
- Unpack_uint32_t(message, &lo);
+ uint32_t high = 0;
+ uint32_t low = 0;
+ Unpack_uint32_t(message, &high);
+ Unpack_uint32_t(message, &low);
assert(value);
- *value = hi;
- *value = *value << 32 | lo;
+ *value = high;
+ *value = *value << 32 | low;
}
void Unpack_OEMCrypto_Substring(ODK_Message* message,
OEMCrypto_Substring* obj) {
- uint32_t offset = 0, length = 0;
+ uint32_t offset = 0;
+ uint32_t length = 0;
Unpack_uint32_t(message, &offset);
Unpack_uint32_t(message, &length);
ODK_Message_Impl* message_impl = GetMessageImpl(message);
- if (!message_impl) return;
+ if (message_impl == NULL) return;
/* 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
@@ -220,11 +253,22 @@ void Unpack_OEMCrypto_Substring(ODK_Message* message,
return;
}
assert(obj);
- obj->offset = offset;
- obj->length = length;
+ obj->offset = (size_t)offset;
+ obj->length = (size_t)length;
}
/* copy out */
void UnpackArray(ODK_Message* message, uint8_t* address, size_t size) {
+ assert(address);
UnpackBytes(message, address, size);
}
+
+void UnpackFixedArray(ODK_Message* message, uint8_t* data, size_t data_length,
+ size_t data_field_size) {
+ assert(data);
+ assert(data_length <= data_field_size);
+ UnpackBytes(message, data, data_length);
+ // Move the counter along the rest of the buffer.
+ SkipBytes(message, data_field_size - data_length);
+ memset(&data[data_length], 0, data_field_size - data_length);
+}
diff --git a/oemcrypto/odk/src/serialization_base.h b/oemcrypto/odk/src/serialization_base.h
index e4b0ef0..9c287a8 100644
--- a/oemcrypto/odk/src/serialization_base.h
+++ b/oemcrypto/odk/src/serialization_base.h
@@ -5,16 +5,16 @@
#ifndef WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
#define WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
#include "OEMCryptoCENCCommon.h"
#include "odk_message.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void Pack_enum(ODK_Message* message, int value);
void Pack_bool(ODK_Message* message, const bool* value);
void Pack_uint8_t(ODK_Message* message, const uint8_t* value);
@@ -22,6 +22,8 @@ void Pack_uint16_t(ODK_Message* message, const uint16_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 PackArray(ODK_Message* message, const uint8_t* base, size_t size);
+void PackFixedArray(ODK_Message* message, const uint8_t* data,
+ size_t data_length, size_t data_field_size);
void Pack_OEMCrypto_Substring(ODK_Message* message,
const OEMCrypto_Substring* obj);
@@ -38,6 +40,8 @@ void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
void UnpackArray(ODK_Message* message, uint8_t* address,
size_t size); /* copy out */
+void UnpackFixedArray(ODK_Message* message, uint8_t* data, size_t data_length,
+ size_t data_field_size);
void Unpack_OEMCrypto_Substring(ODK_Message* message, OEMCrypto_Substring* obj);
#ifdef __cplusplus
diff --git a/oemcrypto/odk/test/fuzzing/Android.bp b/oemcrypto/odk/test/fuzzing/Android.bp
index 6ce3f45..cda0879 100644
--- a/oemcrypto/odk/test/fuzzing/Android.bp
+++ b/oemcrypto/odk/test/fuzzing/Android.bp
@@ -16,166 +16,107 @@ package {
}
cc_defaults {
- name: "odk_fuzz_library_defaults",
+ name: "odk_fuzz_test_defaults",
srcs: [
"odk_fuzz_helper.cpp",
],
- include_dirs: [
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/test",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/include",
- "vendor/widevine/libwvdrmengine/oemcrypto/odk/src",
+ static_libs: [
+ "libwv_kdo",
+ "libwv_odk",
],
+ fuzz_config: {
+ componentid: 611718,
+ },
+ proprietary: true,
+ owner: "widevine",
}
cc_fuzz {
name: "odk_license_request_fuzz",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_license_request_fuzz.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/license_request_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_renewal_request_fuzz",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_renewal_request_fuzz.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/renewal_request_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_provisioning_request_fuzz",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_provisioning_request_fuzz.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/provisioning_request_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_license_response_fuzz",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_license_response_fuzz.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/license_response_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_renewal_response_fuzz",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_renewal_response_fuzz.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/renewal_response_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_provisioning_response_fuzz",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_provisioning_response_fuzz.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/provisioning_response_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_license_response_fuzz_with_mutator",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_license_response_fuzz_with_mutator.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/license_response_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_renewal_response_fuzz_with_mutator",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_renewal_response_fuzz_with_mutator.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/renewal_response_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
cc_fuzz {
name: "odk_provisioning_response_fuzz_with_mutator",
+ defaults: ["odk_fuzz_test_defaults"],
+
srcs: [
"odk_provisioning_response_fuzz_with_mutator.cpp",
],
- fuzz_config: {
- componentid: 611718,
- },
corpus: ["corpus/little_endian_64bit/provisioning_response_corpus/*"],
- static_libs: [
- "libwv_kdo",
- "libwv_odk",
- ],
- defaults: ["odk_fuzz_library_defaults"],
- proprietary: true,
}
diff --git a/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.cpp b/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.cpp
index b7797fd..080d31c 100644
--- a/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.cpp
+++ b/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.cpp
@@ -3,42 +3,94 @@
// License Agreement.
#include "fuzzing/odk_fuzz_helper.h"
+#include
#include
+#include
#include
+#include "OEMCryptoCENCCommon.h"
+#include "core_message_features.h"
#include "core_message_types.h"
+#include "fuzzing/odk_fuzz_structs.h"
#include "odk.h"
#include "odk_attributes.h"
#include "odk_structs.h"
+#include "odk_structs_priv.h"
#include "odk_target.h"
+namespace {
+bool ConvertFuzzedByteToNormalizedBoolean(const bool* in) {
+ constexpr uint8_t kConversionBit = 1;
+ const uint8_t value = *reinterpret_cast(in);
+ return (kConversionBit & value) != 0;
+}
+
+OEMCrypto_LicenseType ConvertFuzzedBytesToNormalizedLicenseType(
+ const OEMCrypto_LicenseType* fuzz_license_type) {
+ // ASAN will trigger an error if fuzz_license_type is dereference directly
+ // before being normalized.
+ using RawEnum = std::underlying_type_t;
+ const RawEnum kLowestValue = static_cast(0);
+ const RawEnum kHighestValue =
+ static_cast(OEMCrypto_LicenseType_MaxValue);
+ const RawEnum kSpan = kHighestValue - kLowestValue + 1;
+ const RawEnum raw_license_type =
+ *reinterpret_cast(fuzz_license_type);
+ return static_cast(
+ ((raw_license_type - kLowestValue) % kSpan) + kLowestValue);
+}
+
+OEMCrypto_TimerDelayBase ConvertFuzzedBytesToNormalizedRenewalDelayBase(
+ const OEMCrypto_TimerDelayBase* fuzz_renewal_delay_base) {
+ // ASAN will trigger an error if fuzz_license_type is dereference directly
+ // before being normalized.
+ using RawEnum = std::underlying_type_t;
+ const RawEnum kLowestValue = static_cast(0);
+ const RawEnum kHighestValue =
+ static_cast(OEMCrypto_TimerDelayBase_MaxValue);
+ const RawEnum kSpan = kHighestValue - kLowestValue + 1;
+ const RawEnum raw_renewal_delay_base =
+ *reinterpret_cast(fuzz_renewal_delay_base);
+ return static_cast(
+ ((raw_renewal_delay_base - kLowestValue) % kSpan) + kLowestValue);
+}
+
+OEMCrypto_PrivateKeyType ConvertFuzzedBytesToNormalizedPrivateKeyType(
+ const OEMCrypto_PrivateKeyType* fuzz_key_type) {
+ using RawEnum = std::underlying_type_t;
+ const RawEnum kLowestValue = static_cast(0);
+ const RawEnum kHighestValue =
+ static_cast(OEMCrypto_PrivateKeyType_MaxValue);
+ const RawEnum kSpan = kHighestValue - kLowestValue + 1;
+ const RawEnum raw_key_type = *reinterpret_cast(fuzz_key_type);
+ return static_cast(
+ ((raw_key_type - kLowestValue) % kSpan) + kLowestValue);
+}
+} // namespace
+
namespace oemcrypto_core_message {
using features::CoreMessageFeatures;
-bool convert_byte_to_valid_boolean(const bool* in) {
- const char* buf = reinterpret_cast(in);
- for (int i = 0; i < sizeof(bool); i++) {
- if (buf[i]) {
- return true;
- }
- }
- return false;
-}
-
-void ConvertDataToValidBools(ODK_ParsedLicense* t) {
+void NormalizeODKStructFields(ODK_ParsedLicense* t) {
// Convert boolean flags in parsed_license to valid bytes to
// avoid errors from msan
- t->nonce_required = convert_byte_to_valid_boolean(&t->nonce_required);
+ t->nonce_required = ConvertFuzzedByteToNormalizedBoolean(&t->nonce_required);
t->timer_limits.soft_enforce_playback_duration =
- convert_byte_to_valid_boolean(
+ ConvertFuzzedByteToNormalizedBoolean(
&t->timer_limits.soft_enforce_playback_duration);
- t->timer_limits.soft_enforce_rental_duration = convert_byte_to_valid_boolean(
- &t->timer_limits.soft_enforce_rental_duration);
+ t->timer_limits.soft_enforce_rental_duration =
+ ConvertFuzzedByteToNormalizedBoolean(
+ &t->timer_limits.soft_enforce_rental_duration);
+ t->license_type = ConvertFuzzedBytesToNormalizedLicenseType(&t->license_type);
+ t->renewal_delay_base =
+ ConvertFuzzedBytesToNormalizedRenewalDelayBase(&t->renewal_delay_base);
}
-void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t UNUSED) {}
+void NormalizeODKStructFields(ODK_PreparedRenewalRequest* t UNUSED) {}
-void ConvertDataToValidBools(ODK_ParsedProvisioning* t UNUSED) {}
+void NormalizeODKStructFields(ODK_ParsedProvisioning* t) {
+ t->key_type = ConvertFuzzedBytesToNormalizedPrivateKeyType(&t->key_type);
+}
OEMCryptoResult odk_serialize_LicenseRequest(
const void* in UNUSED, uint8_t* out, size_t* size,
@@ -47,8 +99,10 @@ OEMCryptoResult odk_serialize_LicenseRequest(
// TODO(mattfedd): hook up counters to fuzzer
const ODK_MessageCounterInfo counter_info = {0, 0, 0, 0, 0,
0, 0, {0}, {0}, {0}};
+ uint16_t decenc_mitigation_options_supported = 0;
return ODK_PrepareCoreLicenseRequest(out, SIZE_MAX, size, nonce_values,
- &counter_info);
+ &counter_info,
+ decenc_mitigation_options_supported);
}
OEMCryptoResult odk_serialize_RenewalRequest(
@@ -93,10 +147,11 @@ OEMCryptoResult odk_deserialize_RenewalResponse(
* errors in fuzzer code and converting random bytes to 0 OR 1.
* This has no negative security impact*/
a->timer_limits.soft_enforce_playback_duration =
- convert_byte_to_valid_boolean(
+ ConvertFuzzedByteToNormalizedBoolean(
&a->timer_limits.soft_enforce_playback_duration);
- a->timer_limits.soft_enforce_rental_duration = convert_byte_to_valid_boolean(
- &a->timer_limits.soft_enforce_rental_duration);
+ a->timer_limits.soft_enforce_rental_duration =
+ ConvertFuzzedByteToNormalizedBoolean(
+ &a->timer_limits.soft_enforce_rental_duration);
uint64_t timer_value = 0;
OEMCryptoResult err =
ODK_ParseRenewal(buf, SIZE_MAX, len, nonce_values, a->system_time,
@@ -128,6 +183,9 @@ OEMCryptoResult odk_deserialize_ProvisioningResponse(
bool kdo_serialize_LicenseResponse(const ODK_ParseLicense_Args* args,
const ODK_ParsedLicense& parsed_lic,
std::string* oemcrypto_core_message) {
+ if (args == nullptr || oemcrypto_core_message == nullptr) {
+ return false;
+ }
const auto& nonce_values = args->nonce_values;
const ODK_MessageCounter counter_info = {0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}};
ODK_LicenseRequest core_request{
@@ -146,11 +204,22 @@ bool kdo_serialize_LicenseResponse(const ODK_ParseLicense_Args* args,
parsed_license.watermarking = parsed_lic.watermarking;
parsed_license.dtcp2_required = parsed_lic.dtcp2_required;
parsed_license.renewal_delay_base = parsed_lic.renewal_delay_base;
+ parsed_license.decenc_mitigation_option_used =
+ parsed_lic.decenc_mitigation_option_used;
+ // If the mutated input for parsed_lic.key_array_length is greater than
+ // 2 * ODK_MAX_NUM_KEYS, then don't bother going through the rest of the
+ // serialization code.
+ if (parsed_lic.key_array_length > 2 * ODK_MAX_NUM_KEYS) return false;
parsed_license.key_array_length = parsed_lic.key_array_length;
- std::vector key_array;
- size_t i;
- for (i = 0; i < parsed_lic.key_array_length && i < ODK_MAX_NUM_KEYS; i++) {
- key_array.push_back(parsed_lic.key_array[i]);
+ std::vector key_array;
+ key_array.reserve(parsed_lic.key_array_length);
+ for (size_t i = 0; i < parsed_lic.key_array_length; i++) {
+ // |parsed_lic| is of type ODK_ParsedLicense which is a struct with a fixed
+ // key array size. Since |parsed_license| is of type
+ // ODK_Packing_ParsedLicense which is a struct with a variable key array
+ // size, we can use a modulus operation to make duplicate keys in
+ // |parsed_license|.
+ key_array.push_back(parsed_lic.key_array[i % ODK_MAX_NUM_KEYS]);
}
parsed_license.key_array = key_array.data();
return serialize::CreateCoreLicenseResponse(
diff --git a/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.h b/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.h
index 309c2be..4d0d29f 100644
--- a/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.h
+++ b/oemcrypto/odk/test/fuzzing/odk_fuzz_helper.h
@@ -4,6 +4,7 @@
#ifndef WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
#define WIDEVINE_ODK_TEST_FUZZING_ODK_FUZZ_HELPER_H_
+#include
#include
#include
@@ -12,10 +13,9 @@
#include "fuzzing/odk_fuzz_structs.h"
#include "odk_attributes.h"
#include "odk_serialize.h"
+#include "odk_structs.h"
namespace oemcrypto_core_message {
-bool convert_byte_to_valid_boolean(const bool* in);
-
OEMCryptoResult odk_serialize_LicenseRequest(
const void* in, uint8_t* out, size_t* size,
const ODK_LicenseRequest& core_license_request,
@@ -66,11 +66,11 @@ bool kdo_serialize_ProvisioningResponse(
// make us of common FuzzerMutateResponse across three response fuzzers,
// three independent functions were defined and renewal and provisioning
// functions would be empty as no additional processing is needed for them.
-void ConvertDataToValidBools(ODK_ParsedLicense* t);
+void NormalizeODKStructFields(ODK_ParsedLicense* t);
-void ConvertDataToValidBools(ODK_PreparedRenewalRequest* t);
+void NormalizeODKStructFields(ODK_PreparedRenewalRequest* t);
-void ConvertDataToValidBools(ODK_ParsedProvisioning* t);
+void NormalizeODKStructFields(ODK_ParsedProvisioning* t);
// Forward-declare the libFuzzer's mutator callback. Mark it weak so that
// the program links successfully even outside of --config=asan-fuzzer
@@ -78,6 +78,16 @@ void ConvertDataToValidBools(ODK_ParsedProvisioning* t);
extern "C" size_t LLVMFuzzerMutate(uint8_t* Data, size_t Size, size_t MaxSize)
__attribute__((weak));
+// 1) ODK message fuzz bytes -> F deserialize -> struct T
+// 2) struct T -> ODK struct fuzzing -> fuzz struct T
+// 2a) struct T -> memcpy + padding -> unnormalized intermediate bytes
+// 2b) unnormalized intermediate bytes -> LLVMFuzzerMutate -> unnormalized
+// intermediate buzz bytes
+// 2c) unnormalized intermediate buzz bytes -> memcpy
+// -> unnormalized struct T
+// 2d) unnormalized struct T ->
+// NormalizeODKStructFields -> fuzz struct T
+// 3) fuzz struct T -> G deserialize -> ODK message
template
size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
const F& odk_deserialize_fun,
@@ -123,8 +133,8 @@ size_t FuzzerMutateResponse(uint8_t* data, size_t size, size_t max_size,
memcpy(args, data, kArgsSize);
memcpy(&t, data + kArgsSize, kCoreResponseSize);
// Convert boolean flags in parsed message to valid bytes to
- // avoid errors from msan. Only needed for parsed license.
- ConvertDataToValidBools(&t);
+ // avoid errors from msan.
+ NormalizeODKStructFields(&t);
// Serialize the data after mutation.
std::string oemcrypto_core_message;
if (!kdo_serialize_fun(args, t, &oemcrypto_core_message)) {
diff --git a/oemcrypto/odk/test/fuzzing/odk_license_response_fuzz_with_mutator.cpp b/oemcrypto/odk/test/fuzzing/odk_license_response_fuzz_with_mutator.cpp
index 735ce7a..0148eb4 100644
--- a/oemcrypto/odk/test/fuzzing/odk_license_response_fuzz_with_mutator.cpp
+++ b/oemcrypto/odk/test/fuzzing/odk_license_response_fuzz_with_mutator.cpp
@@ -15,7 +15,9 @@ extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
size_t max_size,
unsigned int seed UNUSED) {
const size_t kLicenseResponseArgsSize = sizeof(ODK_ParseLicense_Args);
- if (size < kLicenseResponseArgsSize) {
+ const size_t kCoreResponseSize = sizeof(ODK_ParsedLicense);
+ // TODO(b/403349564): Regenerate larger corpuses.
+ if (size < kLicenseResponseArgsSize || size < kCoreResponseSize) {
return 0;
}
diff --git a/oemcrypto/odk/test/fuzzing/odk_renewal_response_fuzz.cpp b/oemcrypto/odk/test/fuzzing/odk_renewal_response_fuzz.cpp
index 416c7b0..d7e0710 100644
--- a/oemcrypto/odk/test/fuzzing/odk_renewal_response_fuzz.cpp
+++ b/oemcrypto/odk/test/fuzzing/odk_renewal_response_fuzz.cpp
@@ -6,6 +6,7 @@
#include
#include "fuzzing/odk_fuzz_helper.h"
+#include "odk_structs_priv.h"
namespace oemcrypto_core_message {
diff --git a/oemcrypto/odk/test/odk_core_message_test.cpp b/oemcrypto/odk/test/odk_core_message_test.cpp
index bea7891..ff2d9bf 100644
--- a/oemcrypto/odk/test/odk_core_message_test.cpp
+++ b/oemcrypto/odk/test/odk_core_message_test.cpp
@@ -42,7 +42,7 @@ TEST(CoreMessageTest, RenwalRequest) {
uint32_t nonce = 0;
uint32_t timer_status = 2;
uint64_t time = 10;
- enum OEMCrypto_Usage_Entry_Status status = kInactiveUsed;
+ enum OEMCrypto_UsageEntryStatus status = OEMCrypto_InactiveUsed;
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce};
ODK_ClockValues clock_values{time, time, time, time,
time, timer_status, status};
@@ -125,8 +125,7 @@ TEST_P(ProvisioningRoundTripTest_18V0, ProvisioningRoundtrip) {
// Make sure we can create a response from that request with the same core
// message
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
std::string serialized_provisioning_resp;
video_widevine::ProvisioningResponse provisioning_response;
provisioning_response.set_device_certificate("device_certificate");
@@ -137,8 +136,8 @@ TEST_P(ProvisioningRoundTripTest_18V0, ProvisioningRoundtrip) {
}
std::string oemcrypto_core_message;
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
- features, serialized_provisioning_resp, request,
- OEMCrypto_RSA_Private_Key, &oemcrypto_core_message));
+ features, serialized_provisioning_resp, request, OEMCrypto_RSAPrivateKey,
+ &oemcrypto_core_message));
// Extract core message from generated prov response and match values with
// request
diff --git a/oemcrypto/odk/test/odk_golden_v16.cpp b/oemcrypto/odk/test/odk_golden_v16.cpp
index 3dcf1f7..cffb507 100644
--- a/oemcrypto/odk/test/odk_golden_v16.cpp
+++ b/oemcrypto/odk/test/odk_golden_v16.cpp
@@ -41,15 +41,14 @@ class ODKGoldenProvisionV16 : public ::testing::Test {
EXPECT_TRUE(CoreProvisioningRequestFromMessage(core_request_,
&core_provisioning_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, provisioning_response_, core_provisioning_request,
device_key_type_, &generated_core_message));
EXPECT_EQ(core_response_, generated_core_message);
}
- OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSA_Private_Key;
+ OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSAPrivateKey;
std::string core_request_;
std::string core_response_;
std::string provisioning_response_;
@@ -62,8 +61,7 @@ class ODKGoldenLicenseV16 : public ::testing::Test {
EXPECT_TRUE(
CoreLicenseRequestFromMessage(core_request_, &core_license_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreLicenseResponseFromProto(
features, serialized_license_, core_license_request,
core_request_sha256_, nonce_required_, uses_padding_,
@@ -86,8 +84,7 @@ class ODKGoldenRenewalV16 : public ::testing::Test {
EXPECT_TRUE(
CoreRenewalRequestFromMessage(core_request_, &core_renewal_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreRenewalResponse(features, core_renewal_request,
renewal_duration_seconds_,
&generated_core_message));
diff --git a/oemcrypto/odk/test/odk_golden_v17.cpp b/oemcrypto/odk/test/odk_golden_v17.cpp
index e1e832c..545c518 100644
--- a/oemcrypto/odk/test/odk_golden_v17.cpp
+++ b/oemcrypto/odk/test/odk_golden_v17.cpp
@@ -41,15 +41,14 @@ class ODKGoldenProvisionV17 : public ::testing::Test {
EXPECT_TRUE(CoreProvisioningRequestFromMessage(core_request_,
&core_provisioning_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, provisioning_response_, core_provisioning_request,
device_key_type_, &generated_core_message));
EXPECT_EQ(core_response_, generated_core_message);
}
- OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSA_Private_Key;
+ OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSAPrivateKey;
std::string core_request_;
std::string core_response_;
std::string provisioning_response_;
@@ -62,8 +61,7 @@ class ODKGoldenLicenseV17 : public ::testing::Test {
EXPECT_TRUE(
CoreLicenseRequestFromMessage(core_request_, &core_license_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreLicenseResponseFromProto(
features, serialized_license_, core_license_request,
core_request_sha256_, nonce_required_, uses_padding_,
@@ -86,8 +84,7 @@ class ODKGoldenRenewalV17 : public ::testing::Test {
EXPECT_TRUE(
CoreRenewalRequestFromMessage(core_request_, &core_renewal_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreRenewalResponse(features, core_renewal_request,
renewal_duration_seconds_,
&generated_core_message));
diff --git a/oemcrypto/odk/test/odk_golden_v18.cpp b/oemcrypto/odk/test/odk_golden_v18.cpp
index acbd8dc..505c6f4 100644
--- a/oemcrypto/odk/test/odk_golden_v18.cpp
+++ b/oemcrypto/odk/test/odk_golden_v18.cpp
@@ -41,15 +41,14 @@ class ODKGoldenProvisionV18 : public ::testing::Test {
EXPECT_TRUE(CoreProvisioningRequestFromMessage(core_request_,
&core_provisioning_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, provisioning_response_, core_provisioning_request,
device_key_type_, &generated_core_message));
EXPECT_EQ(core_response_, generated_core_message);
}
- OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSA_Private_Key;
+ OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSAPrivateKey;
std::string core_request_;
std::string core_response_;
std::string provisioning_response_;
@@ -62,8 +61,7 @@ class ODKGoldenLicenseV18 : public ::testing::Test {
EXPECT_TRUE(
CoreLicenseRequestFromMessage(core_request_, &core_license_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreLicenseResponseFromProto(
features, serialized_license_, core_license_request,
core_request_sha256_, nonce_required_, uses_padding_,
@@ -86,8 +84,7 @@ class ODKGoldenRenewalV18 : public ::testing::Test {
EXPECT_TRUE(
CoreRenewalRequestFromMessage(core_request_, &core_renewal_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreRenewalResponse(features, core_renewal_request,
renewal_duration_seconds_,
&generated_core_message));
@@ -369,7 +366,7 @@ TEST_F(ODKGoldenProvisionV18, CorePIGTest_OfflineNoNonce_prov20) {
provisioning_response_ =
std::string(reinterpret_cast(provisioning_response_raw),
sizeof(provisioning_response_raw));
- device_key_type_ = OEMCrypto_RSA_Private_Key;
+ device_key_type_ = OEMCrypto_RSAPrivateKey;
RunTest();
}
@@ -496,7 +493,7 @@ TEST_F(ODKGoldenProvisionV18, CorePIGTest_OfflineNoNonce_prov20ecc) {
provisioning_response_ =
std::string(reinterpret_cast(provisioning_response_raw),
sizeof(provisioning_response_raw));
- device_key_type_ = OEMCrypto_ECC_Private_Key;
+ device_key_type_ = OEMCrypto_ECCPrivateKey;
RunTest();
}
@@ -760,7 +757,7 @@ TEST_F(ODKGoldenProvisionV18, CorePIGTest_OfflineNoNonce_prov30) {
provisioning_response_ =
std::string(reinterpret_cast(provisioning_response_raw),
sizeof(provisioning_response_raw));
- device_key_type_ = OEMCrypto_RSA_Private_Key;
+ device_key_type_ = OEMCrypto_RSAPrivateKey;
RunTest();
}
diff --git a/oemcrypto/odk/test/odk_golden_v19.cpp b/oemcrypto/odk/test/odk_golden_v19.cpp
index bee6c0d..8099ffa 100644
--- a/oemcrypto/odk/test/odk_golden_v19.cpp
+++ b/oemcrypto/odk/test/odk_golden_v19.cpp
@@ -41,15 +41,14 @@ class ODKGoldenProvisionV19 : public ::testing::Test {
EXPECT_TRUE(CoreProvisioningRequestFromMessage(core_request_,
&core_provisioning_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, provisioning_response_, core_provisioning_request,
device_key_type_, &generated_core_message));
EXPECT_EQ(core_response_, generated_core_message);
}
- OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSA_Private_Key;
+ OEMCrypto_PrivateKeyType device_key_type_ = OEMCrypto_RSAPrivateKey;
std::string core_request_;
std::string core_response_;
std::string provisioning_response_;
@@ -75,8 +74,7 @@ class ODKGoldenLicenseV19 : public ::testing::Test {
EXPECT_TRUE(
CoreLicenseRequestFromMessage(core_request_, &core_license_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreLicenseResponseFromProto(
features, serialized_license_, core_license_request,
core_request_sha256_, nonce_required_, uses_padding_,
@@ -99,8 +97,7 @@ class ODKGoldenRenewalV19 : public ::testing::Test {
EXPECT_TRUE(
CoreRenewalRequestFromMessage(core_request_, &core_renewal_request));
std::string generated_core_message;
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
EXPECT_TRUE(CreateCoreRenewalResponse(features, core_renewal_request,
renewal_duration_seconds_,
&generated_core_message));
@@ -382,7 +379,7 @@ TEST_F(ODKGoldenProvisionV19, CorePIGTest_OfflineNoNonce_prov20) {
provisioning_response_ =
std::string(reinterpret_cast(provisioning_response_raw),
sizeof(provisioning_response_raw));
- device_key_type_ = OEMCrypto_RSA_Private_Key;
+ device_key_type_ = OEMCrypto_RSAPrivateKey;
RunTest();
}
@@ -509,7 +506,7 @@ TEST_F(ODKGoldenProvisionV19, CorePIGTest_OfflineNoNonce_prov20ecc) {
provisioning_response_ =
std::string(reinterpret_cast(provisioning_response_raw),
sizeof(provisioning_response_raw));
- device_key_type_ = OEMCrypto_ECC_Private_Key;
+ device_key_type_ = OEMCrypto_ECCPrivateKey;
RunTest();
}
@@ -773,7 +770,7 @@ TEST_F(ODKGoldenProvisionV19, CorePIGTest_OfflineNoNonce_prov30) {
provisioning_response_ =
std::string(reinterpret_cast(provisioning_response_raw),
sizeof(provisioning_response_raw));
- device_key_type_ = OEMCrypto_RSA_Private_Key;
+ device_key_type_ = OEMCrypto_RSAPrivateKey;
RunTest();
}
diff --git a/oemcrypto/odk/test/odk_test.cpp b/oemcrypto/odk/test/odk_test.cpp
index bd14883..f84e946 100644
--- a/oemcrypto/odk/test/odk_test.cpp
+++ b/oemcrypto/odk/test/odk_test.cpp
@@ -4,6 +4,8 @@
#include "odk.h"
+#include
+
#include
#include
#include
@@ -41,7 +43,6 @@ using oemcrypto_core_message::deserialize::CoreCommonRequestFromMessage;
using oemcrypto_core_message::deserialize::CoreLicenseRequestFromMessage;
using oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage;
using oemcrypto_core_message::deserialize::CoreProvisioningRequestFromMessage;
-using oemcrypto_core_message::deserialize::CoreReleaseRequestFromMessage;
using oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage;
using oemcrypto_core_message::deserialize::
CoreRenewedProvisioningRequestFromMessage;
@@ -61,21 +62,33 @@ constexpr uint32_t kExtraPayloadSize = 128u;
/* Used to parameterize tests by version number. The request is given one
* version number, and we will expect the response to have another version
* number. */
-struct VersionParameters {
- uint32_t maximum_major_version;
- uint16_t request_major_version;
- uint16_t request_minor_version;
- uint16_t response_major_version;
- uint16_t response_minor_version;
+struct VersionPair {
+ uint16_t major_version;
+ uint16_t minor_version;
+
+ template
+ VersionPair(T major, S minor)
+ : major_version(static_cast(major)),
+ minor_version(static_cast(minor)){};
};
+struct VersionParameters {
+ VersionPair maximum; // The CoreMessageFeatures maximum version.
+ bool prerelease; // CoreMessageFeatures serve_prerelease_odk_messages.
+ VersionPair request;
+ VersionPair response;
+ bool should_accept_request;
+};
+
+std::ostream& operator<<(std::ostream& stream, const VersionPair& v) {
+ return stream << "v" << v.major_version << "." << v.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;
+ *os << "max=" << p.maximum << ", prerelease=" << p.prerelease
+ << ", request=" << p.request << ", response=" << p.response
+ << ", should_accept_request=" << p.should_accept_request;
}
void SetDefaultSerializedProvisioningResponse(std::string* serialized_message) {
@@ -147,40 +160,37 @@ void ValidateRequest(uint32_t message_type,
// non-empty buf, expect core message length to be set correctly, and buf is
// filled with ODK_Field values appropriately
- uint8_t* buf = new uint8_t[message_size]{};
+ std::vector buf(message_size, 0);
EXPECT_EQ(OEMCrypto_SUCCESS,
- odk_prepare_func(buf, &core_message_length, &nonce_values));
+ odk_prepare_func(buf.data(), &core_message_length, &nonce_values));
EXPECT_EQ(core_message_length, message_size);
- uint8_t* buf_expected = new uint8_t[message_size]{};
+ std::vector buf_expected(message_size, 0);
size_t buf_len_expected = 0;
- EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, buf_expected, SIZE_MAX,
- &buf_len_expected, total_fields));
+ EXPECT_EQ(OEMCrypto_SUCCESS,
+ ODK_IterFields(ODK_WRITE, buf_expected.data(), SIZE_MAX,
+ &buf_len_expected, total_fields));
EXPECT_EQ(buf_len_expected, message_size);
- EXPECT_NO_FATAL_FAILURE(
- ODK_ExpectEqualBuf(buf_expected, buf, message_size, total_fields));
+ EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf_expected.data(), buf.data(),
+ message_size, total_fields));
// odk kdo round-trip: deserialize from buf, then serialize it to buf2
// expect them to be identical
T t = {};
- std::string oemcrypto_core_message(reinterpret_cast(buf),
+ std::string oemcrypto_core_message(reinterpret_cast(buf.data()),
message_size);
EXPECT_TRUE(kdo_parse_func(oemcrypto_core_message, &t));
nonce_values.api_minor_version = t.api_minor_version;
nonce_values.api_major_version = t.api_major_version;
nonce_values.nonce = t.nonce;
nonce_values.session_id = t.session_id;
- uint8_t* buf2 = new uint8_t[message_size]{};
+ std::vector buf2(message_size, 0);
EXPECT_EQ(OEMCrypto_SUCCESS,
- odk_prepare_func(buf2, &core_message_length, &nonce_values));
+ odk_prepare_func(buf2.data(), &core_message_length, &nonce_values));
EXPECT_EQ(core_message_length, message_size);
EXPECT_NO_FATAL_FAILURE(
- ODK_ExpectEqualBuf(buf, buf2, message_size, total_fields));
-
- delete[] buf;
- delete[] buf_expected;
- delete[] buf2;
+ ODK_ExpectEqualBuf(buf.data(), buf2.data(), message_size, total_fields));
}
/**
@@ -195,40 +205,39 @@ void ValidateResponse(const VersionParameters& versions,
const std::vector& extra_fields,
const F& odk_parse_func, const G& kdo_prepare_func) {
T t = {};
- t.api_major_version = versions.request_major_version;
- t.api_minor_version = versions.request_minor_version;
+ t.api_major_version = versions.request.major_version;
+ t.api_minor_version = versions.request.minor_version;
t.nonce = core_message->nonce_values.nonce;
t.session_id = core_message->nonce_values.session_id;
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(core_message, extra_fields, &buf, &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(core_message, extra_fields, &buf);
- uint8_t* zero = new uint8_t[buf_size]{};
+ std::vector zero(buf.size(), 0);
size_t bytes_read = 0;
// zero-out input
- EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero, buf_size,
+ EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero.data(), buf.size(),
&bytes_read, extra_fields));
// Parse buf with odk
- const OEMCryptoResult parse_result = odk_parse_func(buf, buf_size);
+ const OEMCryptoResult parse_result = odk_parse_func(buf.data(), buf.size());
EXPECT_EQ(OEMCrypto_SUCCESS, parse_result);
size_t size_out = 0;
if (parse_result != OEMCrypto_SUCCESS) {
- ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf, buf_size, &size_out,
+ ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf.data(), buf.size(), &size_out,
extra_fields);
}
// serialize odk output to oemcrypto_core_message
std::string oemcrypto_core_message;
- EXPECT_TRUE(kdo_prepare_func(t, &oemcrypto_core_message));
+ EXPECT_EQ(versions.should_accept_request,
+ kdo_prepare_func(t, &oemcrypto_core_message));
+ if (!versions.should_accept_request) return;
// verify round-trip works
- EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf, oemcrypto_core_message.data(),
- buf_size, extra_fields));
- delete[] buf;
- delete[] zero;
+ EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(
+ buf.data(), oemcrypto_core_message.data(), buf.size(), extra_fields));
}
TEST(OdkTest, SerializeFields) {
@@ -266,26 +275,26 @@ TEST(OdkTest, SerializeFieldsStress) {
total_size += ODK_FieldLength(fields[i].type);
}
- uint8_t* buf = new uint8_t[total_size]{};
+ std::vector buf;
+ buf.reserve(total_size);
for (size_t i = 0; i < total_size; i++) {
- buf[i] = std::rand() & 0xff;
+ buf.push_back(std::rand() & 0xff);
}
size_t bytes_read = 0, bytes_written = 0;
- uint8_t* buf2 = new uint8_t[total_size]{};
- ODK_IterFields(ODK_READ, buf, total_size, &bytes_read, fields);
+ std::vector buf2(total_size);
+ ODK_IterFields(ODK_READ, buf.data(), total_size, &bytes_read, fields);
EXPECT_EQ(bytes_read, total_size);
- ODK_IterFields(ODK_WRITE, buf2, total_size, &bytes_written, fields);
+ ODK_IterFields(ODK_WRITE, buf2.data(), total_size, &bytes_written, fields);
EXPECT_EQ(bytes_written, total_size);
- EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf, buf2, total_size, fields));
+ EXPECT_NO_FATAL_FAILURE(
+ ODK_ExpectEqualBuf(buf.data(), buf2.data(), total_size, fields));
// cleanup
for (int i = 0; i < n; i++) {
free(fields[i].value);
}
- delete[] buf;
- delete[] buf2;
}
TEST(OdkTest, NullRequestTest) {
@@ -296,17 +305,21 @@ TEST(OdkTest, NullRequestTest) {
memset(&clock_values, 0, sizeof(clock_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
+ uint16_t decenc_mitigation_options_supported = 0;
// Assert that nullptr does not cause a core dump.
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(nullptr, 0uL, nullptr, &nonce_values,
- &counter_info));
+ &counter_info,
+ decenc_mitigation_options_supported));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(nullptr, 0uL, &core_message_length,
- nullptr, &counter_info));
+ nullptr, &counter_info,
+ decenc_mitigation_options_supported));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(nullptr, 0uL, &core_message_length,
- &nonce_values, nullptr));
+ &nonce_values, nullptr,
+ decenc_mitigation_options_supported));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewalRequest(nullptr, 0uL, nullptr, &nonce_values,
@@ -479,10 +492,12 @@ TEST(OdkTest, PrepareCoreLicenseRequest) {
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
- EXPECT_EQ(OEMCrypto_SUCCESS,
- ODK_PrepareCoreLicenseRequest(
- license_message, sizeof(license_message), &core_message_length,
- &nonce_values, &counter_info));
+ uint16_t decenc_mitigation_options_supported = 0;
+ EXPECT_EQ(
+ OEMCrypto_SUCCESS,
+ ODK_PrepareCoreLicenseRequest(
+ license_message, sizeof(license_message), &core_message_length,
+ &nonce_values, &counter_info, decenc_mitigation_options_supported));
}
TEST(OdkTest, PrepareCoreLicenseRequestSize) {
@@ -492,18 +507,21 @@ TEST(OdkTest, PrepareCoreLicenseRequestSize) {
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
+ uint16_t decenc_mitigation_options_supported = 0;
// message length smaller than core message length
size_t core_message_length_invalid = core_message_length + 1;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(
license_message, sizeof(license_message),
- &core_message_length_invalid, &nonce_values, &counter_info));
+ &core_message_length_invalid, &nonce_values, &counter_info,
+ decenc_mitigation_options_supported));
// message length larger than core message length
uint8_t license_message_large[ODK_LICENSE_REQUEST_SIZE * 2] = {0};
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreLicenseRequest(
license_message_large, sizeof(license_message_large),
- &core_message_length, &nonce_values, &counter_info));
+ &core_message_length, &nonce_values, &counter_info,
+ decenc_mitigation_options_supported));
}
TEST(OdkTest, PrepareCoreRenewalRequest) {
@@ -641,16 +659,60 @@ TEST(OdkTest, LicenseRequestRoundtrip) {
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
- memset(counter_info.soc_vendor, 0xff, sizeof(counter_info.soc_vendor));
- memset(counter_info.chipset_model, 0xdd, sizeof(counter_info.chipset_model));
+ memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
+ memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
+ uint16_t decenc_mitigation_options_supported = 0;
std::vector extra_fields = {
{ODK_MESSAGECOUNTER, &counter_info, "counter_info"},
+ {ODK_UINT16, &decenc_mitigation_options_supported,
+ "decenc_mitigation_options_supported"},
};
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, nonce_values,
- &counter_info);
+ &counter_info,
+ decenc_mitigation_options_supported);
+ };
+ auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
+ ODK_LicenseRequest* core_license_request) {
+ bool ok = CoreLicenseRequestFromMessage(oemcrypto_core_message,
+ core_license_request);
+ if (!ok) return false;
+
+ ok = CheckCounterInfoIsEqual(&counter_info,
+ &core_license_request->counter_info);
+ return ok;
+ };
+ ValidateRequest(ODK_License_Request_Type, extra_fields,
+ odk_prepare_func, kdo_parse_func);
+}
+
+// Serialize and de-serialize license request that has decenc mitigation
+// non-zero value.
+TEST(OdkTest, LicenseRequestRoundtripDecencMitigation) {
+ ODK_MessageCounterInfo counter_info;
+ counter_info.master_generation_number = 0x12345678abcdffff;
+ counter_info.provisioning_count = 12;
+ counter_info.license_count = 50;
+ counter_info.decrypt_count = 340;
+ counter_info.major_version = ODK_MAJOR_VERSION;
+ counter_info.minor_version = ODK_MINOR_VERSION;
+ counter_info.patch_version = 4;
+ memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
+ memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
+ memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
+ uint16_t decenc_mitigation_options_supported = 1;
+ std::vector extra_fields = {
+ {ODK_MESSAGECOUNTER, &counter_info, "counter_info"},
+ {ODK_UINT16, &decenc_mitigation_options_supported,
+ "decenc_mitigation_options_supported"},
+ };
+ auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
+ ODK_NonceValues* nonce_values) {
+ return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, nonce_values,
+ &counter_info,
+ decenc_mitigation_options_supported);
};
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
ODK_LicenseRequest* core_license_request) {
@@ -692,32 +754,30 @@ TEST(OdkTest, RenewalRequestRoundtrip) {
}
TEST(OdkTest, ReleaseRequestRoundTrip) {
- const uint32_t clock_security_level = 1;
- const uint32_t status = 1;
- constexpr uint64_t system_time_seconds = 0xBADDCAFE000FF1CE;
- uint64_t playback_time = 0xCAFE00000000;
- const int64_t seconds_since_license_requested = 1;
- const int64_t seconds_since_first_decrypt =
- static_cast(system_time_seconds - playback_time);
+ OEMCrypto_UsageEntryStatus usage_entry_status = OEMCrypto_Active;
+ uint32_t clock_security_level = 1;
+ // constexpr uint64_t system_time_seconds = 0xBADDCAFE000FF1CE;
+ uint64_t seconds_since_license_requested = 0;
+ uint64_t seconds_since_first_decrypt = 0;
+ uint32_t pst_length = 1;
+ uint8_t pst[ODK_PST_LEN_MAX];
+ pst[0] = 0xff;
+ // uint8_t* pst_ptr = pst;
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
clock_values.time_of_first_decrypt = seconds_since_first_decrypt;
- std::vector extra_fields = {};
- auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
- ODK_NonceValues* nonce_values) {
- return ODK_PrepareCoreReleaseRequest(
- buf, SIZE_MAX, size, nonce_values, status, clock_security_level,
- seconds_since_license_requested, seconds_since_first_decrypt,
- &clock_values, system_time_seconds);
+ std::vector extra_fields = {
+ {ODK_UINT32, &usage_entry_status, "usage_entry_status"},
+ {ODK_UINT32, &clock_security_level, "clock_security_level"},
+ {ODK_UINT64, &seconds_since_license_requested,
+ "seconds_since_license_requested"},
+ {ODK_UINT64, &seconds_since_first_decrypt, "seconds_since_first_decrypt"},
+ {ODK_UINT32, &pst_length, "pst_length"},
+ {ODK_UINT8, &pst[0], "pst"},
};
- auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
- ODK_ReleaseRequest* core_release_request) {
- bool ok = CoreReleaseRequestFromMessage(oemcrypto_core_message,
- core_release_request);
- return ok;
- };
- ValidateRequest(ODK_Release_Request_Type, extra_fields,
- odk_prepare_func, kdo_parse_func);
+ // TODO(vickymin): Restore the rest of this test after test framework is
+ // updated and fixed. Some variables above are commented out because they
+ // aren't used in the test as of now. This will be updated.
}
TEST(OdkTest, ProvisionRequestRoundtrip) {
@@ -729,8 +789,8 @@ TEST(OdkTest, ProvisionRequestRoundtrip) {
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
- memset(counter_info.soc_vendor, 0xff, sizeof(counter_info.soc_vendor));
- memset(counter_info.chipset_model, 0xdd, sizeof(counter_info.chipset_model));
+ memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
+ memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
// Fake device_id_length for older servers, since we removed device id from
// the v18 request
@@ -772,8 +832,8 @@ TEST(OdkTest, ProvisionRequest40Roundtrip) {
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
- memset(counter_info.soc_vendor, 0xff, sizeof(counter_info.soc_vendor));
- memset(counter_info.chipset_model, 0xdd, sizeof(counter_info.chipset_model));
+ memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
+ memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
std::vector extra_fields = {
{ODK_UINT32, &device_info_length, "device_info_length"},
@@ -837,36 +897,30 @@ TEST(OdkTest, RenewedProvisionRequestRoundtrip) {
TEST(OdkTest, ParseLicenseErrorNonce) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
// temporarily mess up with nonce
params.core_message.nonce_values.nonce = 0;
OEMCryptoResult err = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, 0, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, 0,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(OEMCrypto_ERROR_INVALID_NONCE, err);
- delete[] buf;
}
TEST(OdkTest, ParseLicenseErrorUsageEntry) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
params.usage_entry_present = false;
OEMCryptoResult err = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, 0, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, 0,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
- delete[] buf;
}
TEST(OdkTest, ParseLicenseNullSubstring) {
@@ -874,17 +928,14 @@ TEST(OdkTest, ParseLicenseNullSubstring) {
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);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
OEMCryptoResult result = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, 0, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, 0,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(OEMCrypto_SUCCESS, result);
- delete[] buf;
}
TEST(OdkTest, ParseLicenseErrorSubstringOffset) {
@@ -892,52 +943,43 @@ TEST(OdkTest, ParseLicenseErrorSubstringOffset) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
params.parsed_license.enc_mac_keys_iv.offset = 1024;
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
OEMCryptoResult err = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, 0, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, 0,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
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);
+ params.parsed_license.enc_mac_keys_iv.length = buf.size();
+ buf.clear();
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
err = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, 0, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, 0,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
- delete[] buf;
}
TEST(OdkTest, ParseRenewalErrorTimer) {
ODK_RenewalResponseParams params;
ODK_SetDefaultRenewalResponseParams(¶ms);
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
// Set the time for the last renewal request, as seen in clock_values, to be
// after the time in the request.
// TODO: b/290249855 - This is reversed. It should be +5.
params.clock_values.time_of_renewal_request = params.playback_clock - 5;
OEMCryptoResult err = ODK_ParseRenewal(
- buf, buf_size, buf_size, &(params.core_message.nonce_values),
+ buf.data(), buf.size(), buf.size(), &(params.core_message.nonce_values),
params.system_time, &(params.timer_limits), &(params.clock_values),
&(params.playback_timer));
EXPECT_EQ(ODK_STALE_RENEWAL, err);
- delete[] buf;
}
TEST(OdkTest, ProvisionResponseFromProto) {
@@ -950,12 +992,11 @@ TEST(OdkTest, ProvisionResponseFromProto) {
.nonce = 0xdeadbeef,
.session_id = 0xcafebabe,
};
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
std::string oemcrypto_core_message;
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, serialized_provisioning_resp, core_request,
- OEMCrypto_RSA_Private_Key, &oemcrypto_core_message));
+ OEMCrypto_RSAPrivateKey, &oemcrypto_core_message));
}
// Verify de-serialize common request.
@@ -969,17 +1010,16 @@ TEST(OdkTest, ParseCoreCommonRequestFromMessage) {
.nonce = 0xdeadbeef,
.session_id = 0xcafebabe,
};
- const CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
std::string oemcrypto_core_message;
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, serialized_provisioning_resp, core_request,
- OEMCrypto_RSA_Private_Key, &oemcrypto_core_message));
+ OEMCrypto_RSAPrivateKey, &oemcrypto_core_message));
ODK_CommonRequest odk_common_request;
ASSERT_TRUE(CoreCommonRequestFromMessage(oemcrypto_core_message,
&odk_common_request));
EXPECT_EQ(odk_common_request.message_type, 6u);
- EXPECT_EQ(odk_common_request.message_length, 48u);
+ EXPECT_EQ(odk_common_request.message_length, 60u);
EXPECT_EQ(odk_common_request.api_minor_version, ODK_MINOR_VERSION);
EXPECT_EQ(odk_common_request.api_major_version, ODK_MAJOR_VERSION);
EXPECT_EQ(odk_common_request.nonce, 0xdeadbeef);
@@ -992,15 +1032,14 @@ class OdkVersionTest : public ::testing::Test,
template
void SetRequestVersion(P* params) {
params->core_message.nonce_values.api_major_version =
- GetParam().response_major_version;
+ GetParam().response.major_version;
params->core_message.nonce_values.api_minor_version =
- GetParam().response_minor_version;
- if (GetParam().maximum_major_version > 0) {
- features_ = CoreMessageFeatures::DefaultFeatures(
- GetParam().maximum_major_version);
- } else {
- features_ = CoreMessageFeatures::kDefaultFeatures;
- }
+ GetParam().response.minor_version;
+ features_ = CoreMessageFeatures(GetParam().prerelease);
+ features_.maximum_major_version =
+ static_cast(GetParam().maximum.major_version);
+ features_.maximum_minor_version =
+ static_cast(GetParam().maximum.minor_version);
}
CoreMessageFeatures features_;
};
@@ -1009,7 +1048,7 @@ class OdkVersionTest : public ::testing::Test,
TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms,
- GetParam().response_major_version);
+ GetParam().response.major_version);
SetRequestVersion(¶ms);
// 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
@@ -1037,8 +1076,11 @@ TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
parsed_license.watermarking = params.parsed_license.watermarking;
parsed_license.dtcp2_required = params.parsed_license.dtcp2_required;
parsed_license.renewal_delay_base = params.parsed_license.renewal_delay_base;
+ parsed_license.decenc_mitigation_option_used =
+ params.parsed_license.decenc_mitigation_option_used;
parsed_license.key_array_length = params.parsed_license.key_array_length;
- std::vector key_array;
+ std::vector key_array;
+ key_array.reserve(params.parsed_license.key_array_length);
for (size_t i = 0; i < params.parsed_license.key_array_length; i++) {
key_array.push_back(params.parsed_license.key_array[i]);
}
@@ -1060,9 +1102,12 @@ TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
// Serialize and de-serialize license response with more keys than
// ODK_MAX_NUM_KEYS.
TEST_P(OdkVersionTest, LicenseResponseRoundtripMoreThanMaxKeys) {
+ if (!GetParam().should_accept_request) {
+ GTEST_SKIP() << "Skipping response check because request would be refused.";
+ }
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms,
- GetParam().response_major_version);
+ GetParam().response.major_version);
SetRequestVersion(¶ms);
// 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
@@ -1070,29 +1115,27 @@ TEST_P(OdkVersionTest, LicenseResponseRoundtripMoreThanMaxKeys) {
// will be zero out during the test
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
- uint8_t* zero = new uint8_t[buf_size]{};
+ std::vector zero(buf.size(), 0);
size_t bytes_read = 0;
// zero-out input
EXPECT_EQ(OEMCrypto_SUCCESS,
- ODK_IterFields(ODK_READ, zero, buf_size, &bytes_read,
+ ODK_IterFields(ODK_READ, zero.data(), buf.size(), &bytes_read,
params.extra_fields));
// Parse buf with odk
const OEMCryptoResult parse_result = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, 0, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, 0,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(OEMCrypto_SUCCESS, parse_result);
size_t size_out = 0;
if (parse_result != OEMCrypto_SUCCESS) {
- ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf, buf_size, &size_out,
+ ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf.data(), buf.size(), &size_out,
params.extra_fields);
}
@@ -1108,10 +1151,15 @@ TEST_P(OdkVersionTest, LicenseResponseRoundtripMoreThanMaxKeys) {
parsed_license.watermarking = params.parsed_license.watermarking;
parsed_license.dtcp2_required = params.parsed_license.dtcp2_required;
parsed_license.renewal_delay_base = params.parsed_license.renewal_delay_base;
+ parsed_license.decenc_mitigation_option_used =
+ params.parsed_license.decenc_mitigation_option_used;
parsed_license.key_array_length = ODK_MAX_NUM_KEYS + 1;
- std::vector key_array;
+ std::vector key_array;
for (size_t i = 0; i < ODK_MAX_NUM_KEYS + 1; i++) {
- OEMCrypto_KeyObject key = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}};
+ OEMCrypto_KeyObjectV2 key = {
+ {0, 0}, {0, 0},
+ {0, 0}, {0, 0},
+ {0, 0}, {OEMCrypto_DeCENC_Mitigation_Option_None, {{{0, 0}, {0, 0}}}}};
key_array.push_back(key);
}
parsed_license.key_array = key_array.data();
@@ -1122,20 +1170,76 @@ TEST_P(OdkVersionTest, LicenseResponseRoundtripMoreThanMaxKeys) {
// serialize odk output to oemcrypto_core_message
std::string oemcrypto_core_message;
ODK_LicenseRequest core_request = {};
- core_request.api_major_version = GetParam().request_major_version;
- core_request.api_minor_version = GetParam().request_minor_version;
+ core_request.api_major_version = GetParam().request.major_version;
+ core_request.api_minor_version = GetParam().request.minor_version;
core_request.nonce = params.core_message.nonce_values.nonce;
core_request.session_id = params.core_message.nonce_values.session_id;
bool result =
CreateCoreLicenseResponse(features_, parsed_license, core_request,
request_hash_string, &oemcrypto_core_message);
- EXPECT_TRUE(result);
+ EXPECT_EQ(GetParam().should_accept_request, result);
+}
- delete[] buf;
- delete[] zero;
+// Serialize and de-serialize license response
+TEST_P(OdkVersionTest, LicenseResponseRoundtripDecencMitigation) {
+ ODK_LicenseResponseParams params;
+ ODK_SetDefaultLicenseResponseParamsDecencMitigation(
+ ¶ms, GetParam().response.major_version,
+ GetParam().response.minor_version);
+ SetRequestVersion(¶ms);
+ // 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];
+ memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
+ auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
+ return ODK_ParseLicense(
+ buf, size + kExtraPayloadSize, size, params.initial_license_load,
+ params.usage_entry_present, 0, &(params.timer_limits),
+ &(params.clock_values), &(params.core_message.nonce_values),
+ &(params.parsed_license), nullptr);
+ };
+
+ ODK_Packing_ParsedLicense parsed_license;
+ parsed_license.enc_mac_keys_iv = params.parsed_license.enc_mac_keys_iv;
+ parsed_license.enc_mac_keys = params.parsed_license.enc_mac_keys;
+ parsed_license.pst = params.parsed_license.pst;
+ parsed_license.srm_restriction_data =
+ params.parsed_license.srm_restriction_data;
+ parsed_license.license_type = params.parsed_license.license_type;
+ parsed_license.nonce_required = params.parsed_license.nonce_required;
+ parsed_license.timer_limits = params.parsed_license.timer_limits;
+ parsed_license.watermarking = params.parsed_license.watermarking;
+ parsed_license.dtcp2_required = params.parsed_license.dtcp2_required;
+ parsed_license.renewal_delay_base = params.parsed_license.renewal_delay_base;
+ parsed_license.decenc_mitigation_option_used =
+ params.parsed_license.decenc_mitigation_option_used;
+ parsed_license.key_array_length = params.parsed_license.key_array_length;
+ std::vector key_array;
+ key_array.reserve(params.parsed_license.key_array_length);
+ for (size_t i = 0; i < params.parsed_license.key_array_length; i++) {
+ key_array.push_back(params.parsed_license.key_array[i]);
+ }
+ parsed_license.key_array = key_array.data();
+ const std::string request_hash_string(
+ reinterpret_cast(request_hash_read),
+ sizeof(request_hash_read));
+ auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
+ std::string* oemcrypto_core_message) {
+ return CreateCoreLicenseResponse(features_, parsed_license, core_request,
+ request_hash_string,
+ oemcrypto_core_message);
+ };
+ ValidateResponse(GetParam(), &(params.core_message),
+ params.extra_fields, odk_parse_func,
+ kdo_prepare_func);
}
TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
+ if (!GetParam().should_accept_request) {
+ GTEST_SKIP() << "Skipping renewal test because request would be refused.";
+ }
ODK_RenewalResponseParams params;
ODK_SetDefaultRenewalResponseParams(¶ms);
SetRequestVersion(¶ms);
@@ -1166,23 +1270,20 @@ TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
}
TEST_P(OdkVersionTest, ReleaseResponseRoundtrip) {
+ if (!GetParam().should_accept_request) {
+ GTEST_SKIP() << "Skipping release test because request would be refused.";
+ }
ODK_ReleaseResponseParams params;
ODK_SetDefaultReleaseResponseParams(¶ms);
SetRequestVersion(¶ms);
- const int64_t seconds_since_license_requested =
- params.seconds_since_license_requested;
- const int64_t seconds_since_first_decrypt =
- params.seconds_since_first_decrypt;
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
- OEMCryptoResult err =
- ODK_ParseRelease(buf, size, size, &(params.core_message.nonce_values));
- return err;
+ return ODK_ParseRelease(buf, size, size,
+ &(params.core_message.nonce_values));
};
auto kdo_prepare_func = [&](ODK_ReleaseRequest& core_request,
std::string* oemcrypto_core_message) {
- return CreateCoreReleaseResponse(
- features_, core_request, seconds_since_license_requested,
- seconds_since_first_decrypt, oemcrypto_core_message);
+ return CreateCoreReleaseResponse(features_, core_request,
+ oemcrypto_core_message);
};
ValidateResponse(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
@@ -1192,7 +1293,7 @@ TEST_P(OdkVersionTest, ReleaseResponseRoundtrip) {
TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
ODK_ProvisioningResponseParams params;
ODK_SetDefaultProvisioningResponseParams(¶ms,
- GetParam().response_major_version);
+ GetParam().response.major_version);
SetRequestVersion(¶ms);
// save a copy of params.device_id as it will be zero out during the test
const uint32_t device_id_length = params.device_id_length;
@@ -1200,9 +1301,13 @@ TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
memcpy(device_id, params.device_id, device_id_length);
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
- OEMCryptoResult err = ODK_ParseProvisioning(
- buf, size + 16, size, &(params.core_message.nonce_values), device_id,
- device_id_length, &(params.parsed_provisioning));
+ // This constant represents the additional space needed for the message
+ // length on top of the core message size.
+ constexpr size_t kProvResponsePayloadSize = 18;
+ OEMCryptoResult err =
+ ODK_ParseProvisioning(buf, size + kProvResponsePayloadSize, size,
+ &(params.core_message.nonce_values), device_id,
+ device_id_length, &(params.parsed_provisioning));
return err;
};
auto kdo_prepare_func = [&](ODK_ProvisioningRequest& core_request,
@@ -1216,6 +1321,7 @@ TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
return CreateCoreProvisioningResponse(features_, params.parsed_provisioning,
core_request, oemcrypto_core_message);
};
+
ValidateResponse(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
kdo_prepare_func);
@@ -1242,68 +1348,82 @@ TEST_P(OdkVersionTest, Provision40ResponseRoundtrip) {
}
// If the minor version is positive, we can test an older minor version.
-const uint16_t kOldMinor = ODK_MINOR_VERSION > 0 ? ODK_MINOR_VERSION - 1 : 0;
+constexpr uint16_t kOldMinor =
+ ODK_MINOR_VERSION > 0 ? ODK_MINOR_VERSION - 1 : 0;
// Similarly, if this isn't the first major version, we can test an older major
// version.
-const uint16_t kOldMajor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION
- ? ODK_MAJOR_VERSION - 1
- : ODK_FIRST_VERSION;
+constexpr uint16_t kOldMajor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION
+ ? ODK_MAJOR_VERSION - 1
+ : ODK_FIRST_VERSION;
// If there is an older major, then we should accept any minor version.
// Otherwise, this test won't make sense and we should just use a minor of 0.
-const uint16_t kOldMajorMinor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION ? 42 : 0;
+constexpr 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. This list is a little bit fragile,
+// everytime we release a new version the list has to be updated.
std::vector TestCases() {
+ const VersionPair latest(ODK_MAJOR_VERSION, ODK_MINOR_VERSION);
+ const VersionPair previous(ODK_MAJOR_VERSION, kOldMinor);
+ const VersionPair next_minor(ODK_MAJOR_VERSION, ODK_MINOR_VERSION + 1);
+ // The next major release with minor=0 is a prerelease.
+ const VersionPair next_major_prerelease(ODK_MAJOR_VERSION + 1, 0);
+ // The next major release with minor>0 is a release.
+ const VersionPair next_major_release(ODK_MAJOR_VERSION + 1, 42);
+ const VersionPair previous_major(kOldMajor, kOldMajorMinor);
+ const VersionPair latest_prerelease(ODK_MAJOR_VERSION, 0);
+ const VersionPair previous_prerelease(kOldMajor, 0);
+ const VersionPair latest_released(
+ CoreMessageFeatures::kDefaultFeatures.maximum_major_version,
+ CoreMessageFeatures::kDefaultFeatures.maximum_minor_version);
+ const VersionPair v16(16, 5);
+ const VersionPair v17(17, 6);
+ const VersionPair v18(18, 8);
+ const VersionPair v19(19, 5);
+ const VersionPair v20_prerelease(20, 0);
+ const VersionPair v20(20, 1);
+
std::vector test_cases{
- // Fields: maximum 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_MAJOR_VERSION, kOldMajor, 0, kOldMajor, 0},
- {ODK_MAJOR_VERSION, kOldMajor, kOldMajorMinor, kOldMajor, kOldMajorMinor},
- // If the server is restricted to v16, then the response can be at
- // most 16.5
- // These tests cases must be updated whenever we roll the minor version
- // number.
- {16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5},
- {17, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 17, 2},
- {18, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 18, 4},
- {19, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 19, 5},
- // Here are some known good versions. Make extra sure they work.
- {ODK_MAJOR_VERSION, 16, 3, 16, 3},
- {ODK_MAJOR_VERSION, 16, 4, 16, 4},
- {ODK_MAJOR_VERSION, 16, 5, 16, 5},
- {ODK_MAJOR_VERSION, 17, 1, 17, 1},
- {ODK_MAJOR_VERSION, 17, 2, 17, 2},
- {ODK_MAJOR_VERSION, 18, 1, 18, 1},
- {ODK_MAJOR_VERSION, 18, 2, 18, 2},
- {ODK_MAJOR_VERSION, 18, 3, 18, 3},
- {ODK_MAJOR_VERSION, 19, 0, 19, 0},
- {ODK_MAJOR_VERSION, 19, 1, 19, 1},
- {ODK_MAJOR_VERSION, 19, 2, 19, 2},
- {ODK_MAJOR_VERSION, 19, 3, 19, 3},
- {ODK_MAJOR_VERSION, 19, 4, 19, 4},
- {ODK_MAJOR_VERSION, 19, 5, 19, 5},
- {0, 16, 3, 16, 3},
- {0, 16, 4, 16, 4},
- {0, 16, 5, 16, 5},
- {0, 17, 1, 17, 1},
- {0, 17, 2, 17, 2},
- {0, 18, 3, 18, 3},
- {0, 18, 4, 18, 4},
- {0, 19, 0, 19, 0},
- {0, 19, 1, 19, 1},
- {0, 19, 2, 19, 2},
- {0, 19, 3, 19, 3},
- {0, 19, 4, 19, 4},
- {0, 19, 5, 19, 5},
+ // Fields: maximum, prerelease, request, response, should_accept_request.
+ {latest, true, latest, latest, true},
+ {latest, true, next_minor, latest, true},
+ {latest, true, previous, previous, true},
+ {latest, true, previous_major, previous_major, true},
+ {latest, true, next_minor, latest, true},
+ {latest, true, next_major_prerelease, latest, true},
+ {latest, true, next_major_release, latest, true},
+ {latest, true, latest_prerelease, latest_prerelease, true},
+ {latest, true, previous_prerelease, previous_prerelease, true},
+
+ {v16, true, latest, v16, true},
+ {v17, true, latest, v17, true},
+ {v18, true, latest, v18, true},
+ {v19, true, latest, v19, true},
+
+ {latest, true, v16, v16, true},
+ {latest, true, v17, v17, true},
+ {latest, true, v18, v18, true},
+ {latest, true, v19, v19, true},
+ {latest, true, v20_prerelease, v20_prerelease, true},
+ {latest, true, v20, latest, true}, // Change this when v20.1 is released.
+
+ // From here on, the serve is restricted to the released version.
+ {latest_released, false, v16, v16, true},
+ {latest_released, false, v17, v17, true},
+ {latest_released, false, v18, v18, true},
+ {latest_released, false, v19, v19, true},
+ // TODO(b/403381396): change the response version to v20 after v20 has
+ // been released.
+ {latest_released, false, v20, latest_released, true},
+ {latest_released, false, next_minor, latest_released, true},
+
+ // Prerelease requests should not be accepted.
+ {latest_released, false, v20_prerelease, v20_prerelease, false},
+ {latest_released, false, latest_prerelease, latest_prerelease, false},
+
+ // Future pre-release and release are OK, for back compat testing.
+ {latest_released, false, next_major_prerelease, latest_released, true},
+ {latest_released, false, next_major_release, latest_released, true},
};
return test_cases;
}
@@ -1321,12 +1441,13 @@ TEST(OdkSizeTest, LicenseRequest) {
uint32_t session_id = 0;
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
+ uint16_t decenc_mitigation_options_supported = 0;
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce,
session_id};
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
- ODK_PrepareCoreLicenseRequest(message, message_length,
- &core_message_length, &nonce_values,
- &counter_info));
+ ODK_PrepareCoreLicenseRequest(
+ message, message_length, &core_message_length, &nonce_values,
+ &counter_info, decenc_mitigation_options_supported));
// the core_message_length should be appropriately set
if (nonce_values.api_major_version > 17) {
EXPECT_EQ(ODK_LICENSE_REQUEST_SIZE, core_message_length);
diff --git a/oemcrypto/odk/test/odk_test_helper.cpp b/oemcrypto/odk/test/odk_test_helper.cpp
index 184515d..24ffa7d 100644
--- a/oemcrypto/odk/test/odk_test_helper.cpp
+++ b/oemcrypto/odk/test/odk_test_helper.cpp
@@ -18,6 +18,7 @@
#include "OEMCryptoCENCCommon.h"
#include "gtest/gtest.h"
#include "odk_endian.h"
+#include "odk_serialize.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
@@ -78,7 +79,8 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
.length = 3,
.data = {0, 0, 0},
}},
- .renewal_delay_base = OEMCrypto_License_Start,
+ .renewal_delay_base = OEMCrypto_LicenseStart,
+ .decenc_mitigation_option_used = 0,
.key_array_length = 3,
.key_array =
{
@@ -212,7 +214,10 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
{ODK_UINT32, &(params->parsed_license.renewal_delay_base),
".renewal_delay_base"});
}
- params->extra_fields.push_back({ODK_UINT32,
+ params->extra_fields.push_back(
+ {ODK_UINT16, &(params->parsed_license.decenc_mitigation_option_used),
+ ".decenc_mitigation_option_used"});
+ params->extra_fields.push_back({ODK_UINT16,
&(params->parsed_license.key_array_length),
".key_array_length"});
params->extra_fields.push_back({ODK_SUBSTRING,
@@ -266,12 +271,337 @@ void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
}
}
+void ODK_SetDefaultLicenseResponseParamsDecencMitigation(
+ ODK_LicenseResponseParams* params, uint32_t odk_major_version,
+ uint32_t odk_minor_version) {
+ ODK_SetDefaultCoreFields(&(params->core_message), ODK_License_Response_Type);
+ params->initial_license_load = true;
+ params->usage_entry_present = true;
+ params->parsed_license = {
+ .enc_mac_keys_iv = {.offset = 0, .length = 1},
+ .enc_mac_keys = {.offset = 2, .length = 3},
+ .pst = {.offset = 4, .length = 5},
+ .srm_restriction_data = {.offset = 6, .length = 7},
+ .license_type = OEMCrypto_EntitlementLicense,
+ .nonce_required = true,
+ .timer_limits =
+ {
+ .soft_enforce_rental_duration = true,
+ .soft_enforce_playback_duration = false,
+ .earliest_playback_start_seconds = 10,
+ .rental_duration_seconds = 11,
+ .total_playback_duration_seconds = 12,
+ .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},
+ }},
+ .renewal_delay_base = OEMCrypto_LicenseStart,
+ .decenc_mitigation_option_used = ODK_VersionSupportsDecencMitigation(
+ odk_major_version, odk_minor_version),
+ .key_array_length = 3,
+ .key_array =
+ {
+ {
+ .key_id = {.offset = 15, .length = 16},
+ .key_data_iv = {.offset = 17, .length = 18},
+ .key_data = {.offset = 19, .length = 20},
+ .key_control_iv = {.offset = 21, .length = 22},
+ .key_control = {.offset = 23, .length = 24},
+ },
+ {
+ .key_id = {.offset = 25, .length = 26},
+ .key_data_iv = {.offset = 27, .length = 28},
+ .key_data = {.offset = 29, .length = 30},
+ .key_control_iv = {.offset = 31, .length = 32},
+ .key_control = {.offset = 33, .length = 34},
+ },
+ {
+ .key_id = {.offset = 35, .length = 36},
+ .key_data_iv = {.offset = 37, .length = 38},
+ .key_data = {.offset = 39, .length = 40},
+ .key_control_iv = {.offset = 41, .length = 42},
+ .key_control = {.offset = 43, .length = 44},
+ },
+ },
+ };
+ // Set decenc mitigation info if decenc mitigation is requested by the content
+ // provider.
+ if (params->parsed_license.decenc_mitigation_option_used != 0) {
+ auto& key_array = params->parsed_license.key_array;
+ for (uint16_t i = 0; i < params->parsed_license.key_array_length; i++) {
+ key_array[i].decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream;
+ auto& auth_key_info = key_array[i]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info;
+ auth_key_info.authentication_key =
+ (OEMCrypto_Substring){.offset = 25, .length = 26};
+ auth_key_info.authentication_key_iv =
+ (OEMCrypto_Substring){.offset = 27, .length = 28};
+ }
+ }
+ memset(params->request_hash, 0xaa, sizeof(params->request_hash));
+ params->extra_fields = {
+ {ODK_SUBSTRING, &(params->parsed_license.enc_mac_keys_iv),
+ ".enc_mac_keys_iv"},
+ {ODK_SUBSTRING, &(params->parsed_license.enc_mac_keys), ".enc_mac_keys"},
+ {ODK_SUBSTRING, &(params->parsed_license.pst), ".pst"},
+ {ODK_SUBSTRING, &(params->parsed_license.srm_restriction_data),
+ ".srm_restriction_data"},
+ {ODK_UINT32, &(params->parsed_license.license_type), ".license_type"},
+ {ODK_UINT32, &(params->parsed_license.nonce_required), ".nonce_required"},
+ {ODK_BOOL,
+ &(params->parsed_license.timer_limits.soft_enforce_rental_duration),
+ ".soft_enforce_rental_duration"},
+ {ODK_BOOL,
+ &(params->parsed_license.timer_limits.soft_enforce_playback_duration),
+ ".soft_enforce_playback_duration"},
+ {ODK_UINT64,
+ &(params->parsed_license.timer_limits.earliest_playback_start_seconds),
+ ".earliest_playback_start_seconds"},
+ {ODK_UINT64,
+ &(params->parsed_license.timer_limits.rental_duration_seconds),
+ ".rental_duration_seconds"},
+ {ODK_UINT64,
+ &(params->parsed_license.timer_limits.total_playback_duration_seconds),
+ ".total_playback_duration_seconds"},
+ {ODK_UINT64,
+ &(params->parsed_license.timer_limits.initial_renewal_duration_seconds),
+ ".initial_renewal_duration_seconds"},
+ };
+ 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"});
+ }
+ }
+ if (odk_major_version >= 18) {
+ params->extra_fields.push_back(
+ {ODK_UINT32, &(params->parsed_license.renewal_delay_base),
+ ".renewal_delay_base"});
+ }
+ params->extra_fields.push_back(
+ {ODK_UINT16, &(params->parsed_license.decenc_mitigation_option_used),
+ ".decenc_mitigation_option_used"});
+ params->extra_fields.push_back({ODK_UINT16,
+ &(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"});
+ if (params->parsed_license.decenc_mitigation_option_used != 0 &&
+ ODK_VersionSupportsDecencMitigation(odk_major_version,
+ odk_minor_version)) {
+ params->extra_fields.push_back(
+ {ODK_UINT32,
+ &(params->parsed_license.key_array[0]
+ .decenc_mitigation_info.mitigation_option),
+ ".mitigation_option"});
+ if (params->parsed_license.key_array[0]
+ .decenc_mitigation_info.mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream) {
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_license.key_array[0]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info.authentication_key),
+ ".authentication_key"});
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_license.key_array[0]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info.authentication_key_iv),
+ ".authentication_key_iv"});
+ }
+ }
+ 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"});
+ if (params->parsed_license.decenc_mitigation_option_used != 0 &&
+ ODK_VersionSupportsDecencMitigation(odk_major_version,
+ odk_minor_version)) {
+ params->extra_fields.push_back(
+ {ODK_UINT32,
+ &(params->parsed_license.key_array[1]
+ .decenc_mitigation_info.mitigation_option),
+ ".mitigation_option"});
+ if (params->parsed_license.key_array[1]
+ .decenc_mitigation_info.mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream) {
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_license.key_array[1]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info.authentication_key),
+ ".authentication_key"});
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_license.key_array[1]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info.authentication_key_iv),
+ ".authentication_key_iv"});
+ }
+ }
+ 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 (params->parsed_license.decenc_mitigation_option_used != 0 &&
+ ODK_VersionSupportsDecencMitigation(odk_major_version,
+ odk_minor_version)) {
+ params->extra_fields.push_back(
+ {ODK_UINT32,
+ &(params->parsed_license.key_array[2]
+ .decenc_mitigation_info.mitigation_option),
+ ".mitigation_option"});
+ if (params->parsed_license.key_array[2]
+ .decenc_mitigation_info.mitigation_option ==
+ OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream) {
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_license.key_array[2]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info.authentication_key),
+ ".authentication_key"});
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_license.key_array[2]
+ .decenc_mitigation_info.configuration_options
+ .authentication_key_info.authentication_key_iv),
+ ".authentication_key_iv"});
+ }
+ }
+ if (odk_major_version == 16) {
+ params->extra_fields.push_back(
+ {ODK_HASH, params->request_hash, ".request_hash"});
+ }
+}
+
void ODK_SetDefaultReleaseResponseParams(ODK_ReleaseResponseParams* params) {
ODK_SetDefaultCoreFields(&(params->core_message), ODK_Release_Response_Type);
- params->status = kActive;
- params->clock_security_level = 0;
- params->seconds_since_license_requested = 0;
- params->seconds_since_first_decrypt = 0;
}
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) {
@@ -300,7 +630,7 @@ void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params) {
.time_of_renewal_request = params->playback_clock,
.time_when_timer_expires = params->system_time + params->playback_timer,
.timer_status = ODK_CLOCK_TIMER_STATUS_ACTIVE,
- .status = kActive,
+ .status = OEMCrypto_Active,
};
}
@@ -313,10 +643,14 @@ void ODK_SetDefaultProvisioningResponseParams(
memset(params->device_id + params->device_id_length, 0,
ODK_DEVICE_ID_LEN_MAX - params->device_id_length);
params->parsed_provisioning = {
- .key_type = OEMCrypto_RSA_Private_Key,
+ .key_type = OEMCrypto_RSAPrivateKey,
.enc_private_key = {.offset = 0, .length = 1},
.enc_private_key_iv = {.offset = 2, .length = 3},
.encrypted_message_key = {.offset = 4, .length = 5},
+ .curr_server_sealing_key = {.offset = 6, .length = 7},
+ .server_sealing_key_array_length = 1,
+ .server_sealing_key_array = {(OEMCrypto_Substring){.offset = 8,
+ .length = 9}},
};
params->extra_fields = {};
@@ -339,6 +673,20 @@ void ODK_SetDefaultProvisioningResponseParams(
params->extra_fields.push_back(
{ODK_SUBSTRING, &(params->parsed_provisioning).encrypted_message_key,
"encrypted_message_key"});
+
+ if (odk_major_version >= 20) {
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING, &(params->parsed_provisioning).curr_server_sealing_key,
+ "curr_server_sealing_key"});
+ params->extra_fields.push_back(
+ {ODK_UINT32,
+ &(params->parsed_provisioning).server_sealing_key_array_length,
+ "server_sealing_key_array_length"});
+ params->extra_fields.push_back(
+ {ODK_SUBSTRING,
+ &(params->parsed_provisioning).server_sealing_key_array[0],
+ "server_sealing_key"});
+ }
}
void ODK_SetDefaultProvisioning40ResponseParams(
@@ -358,8 +706,6 @@ size_t ODK_FieldLength(ODK_FieldType type) {
return sizeof(uint32_t);
case ODK_UINT64:
return sizeof(uint64_t);
- case ODK_INT64:
- return sizeof(uint64_t);
case ODK_SUBSTRING:
return sizeof(uint32_t) + sizeof(uint32_t);
case ODK_DEVICEID:
@@ -414,12 +760,6 @@ OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field) {
memcpy(buf, &u64, sizeof(u64));
break;
}
- case ODK_INT64: {
- const int64_t i64 =
- oemcrypto_htobe64(*static_cast(field->value));
- memcpy(buf, &i64, sizeof(i64));
- break;
- }
case ODK_BOOL: {
const bool value = *static_cast(field->value);
const uint32_t u32 = oemcrypto_htobe32(value ? 1 : 0);
@@ -499,12 +839,6 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
*u64p = oemcrypto_be64toh(*u64p);
break;
}
- case ODK_INT64: {
- memcpy(field->value, buf, sizeof(int64_t));
- int64_t* i64p = static_cast(field->value);
- *i64p = oemcrypto_be64toh(*i64p);
- break;
- }
case ODK_BOOL: {
uint32_t value;
memcpy(&value, buf, sizeof(uint32_t));
@@ -624,19 +958,13 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
<< "\n";
break;
}
- case ODK_INT64: {
- int64_t val;
- memcpy(&val, buf, sizeof(int64_t));
- val = oemcrypto_be64toh(val);
- std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
- << "\n";
- break;
- }
case ODK_SUBSTRING: {
uint32_t off = 0;
uint32_t len = 0;
memcpy(&off, buf, sizeof(off));
memcpy(&len, buf + sizeof(off), sizeof(len));
+ off = oemcrypto_be32toh(off);
+ len = oemcrypto_be32toh(len);
std::cerr << field->name << ": (off=" << off << ", len=" << len << ")\n";
break;
}
@@ -723,13 +1051,13 @@ std::vector ODK_MakeTotalFields(
}
// Expect the two buffers of size n to be equal. If not, dump the messages.
-void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
+void ODK_ExpectEqualBuf(const void* expected, const void* actual, size_t n,
const std::vector& fields) {
- if (memcmp(s1, s2, n) != 0) {
+ if (memcmp(expected, actual, n) != 0) {
ODK_CoreMessage core_message;
std::vector total_fields =
ODK_MakeTotalFields(fields, &core_message);
- const void* buffers[] = {s1, s2};
+ const void* buffers[] = {expected, actual};
for (int i = 0; i < 2; i++) {
char _tmp[] = "/tmp/fileXXXXXX";
const int temp_fd = mkstemp(_tmp);
@@ -744,7 +1072,8 @@ void ODK_ExpectEqualBuf(const void* s1, const void* s2, size_t n,
out.write(static_cast(buffers[i]), n);
out.close();
std::cerr << '\n'
- << "Message buffer " << i << " dumped to " << tmp << '\n';
+ << "Message buffer " << i << (i == 0 ? " expected" : " actual")
+ << " dumped to " << tmp << '\n';
size_t bytes_written;
uint8_t* buf =
const_cast(reinterpret_cast(buffers[i]));
@@ -768,24 +1097,25 @@ void ODK_ResetOdkFields(std::vector* fields) {
void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
const std::vector& extra_fields,
- uint8_t** buf, uint32_t* buf_size) {
+ std::vector* buf) {
ASSERT_TRUE(core_message != nullptr);
- ASSERT_TRUE(buf_size != nullptr);
+ ASSERT_TRUE(buf != nullptr);
std::vector total_fields =
ODK_MakeTotalFields(extra_fields, core_message);
+ uint32_t buf_size = 0;
for (auto& field : total_fields) {
- *buf_size += ODK_FieldLength(field.type);
+ buf_size += ODK_FieldLength(field.type);
}
// update message_size
- *(reinterpret_cast(total_fields[1].value)) = *buf_size;
+ *(reinterpret_cast(total_fields[1].value)) = buf_size;
- *buf = new uint8_t[*buf_size]{};
+ buf->resize(buf_size);
size_t bytes_written = 0;
// serialize ODK fields to message buffer
- EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, *buf, SIZE_MAX,
+ EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, buf->data(), SIZE_MAX,
&bytes_written, total_fields));
- EXPECT_EQ(bytes_written, *buf_size);
+ EXPECT_EQ(bytes_written, buf_size);
}
} // namespace wvodk_test
diff --git a/oemcrypto/odk/test/odk_test_helper.h b/oemcrypto/odk/test/odk_test_helper.h
index 5005b94..f52bb7d 100644
--- a/oemcrypto/odk/test/odk_test_helper.h
+++ b/oemcrypto/odk/test/odk_test_helper.h
@@ -20,7 +20,6 @@ enum ODK_FieldType {
ODK_UINT16,
ODK_UINT32,
ODK_UINT64,
- ODK_INT64,
ODK_SUBSTRING,
ODK_DEVICEID,
ODK_DEVICEINFO,
@@ -62,10 +61,6 @@ struct ODK_LicenseResponseParams {
struct ODK_ReleaseResponseParams {
ODK_CoreMessage core_message;
- uint32_t status;
- uint32_t clock_security_level;
- int64_t seconds_since_license_requested;
- int64_t seconds_since_first_decrypt;
std::vector extra_fields;
};
@@ -99,6 +94,9 @@ void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
ODK_MessageType message_type);
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
uint32_t odk_major_version);
+void ODK_SetDefaultLicenseResponseParamsDecencMitigation(
+ ODK_LicenseResponseParams* params, uint32_t odk_major_version,
+ uint32_t odk_minor_version);
void ODK_SetDefaultReleaseResponseParams(ODK_ReleaseResponseParams* params);
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params);
void ODK_SetDefaultProvisioningResponseParams(
@@ -124,7 +122,7 @@ void ODK_ResetOdkFields(std::vector* fields);
// Serialize core_message and extra_fields into buf
void ODK_BuildMessageBuffer(ODK_CoreMessage* core_message,
const std::vector& extra_fields,
- uint8_t** buf, uint32_t* buf_size);
+ std::vector* buf);
} // namespace wvodk_test
diff --git a/oemcrypto/odk/test/odk_timer_test.cpp b/oemcrypto/odk/test/odk_timer_test.cpp
index 1190cf0..692d62a 100644
--- a/oemcrypto/odk/test/odk_timer_test.cpp
+++ b/oemcrypto/odk/test/odk_timer_test.cpp
@@ -3,6 +3,9 @@
* License Agreement.
*/
+#include
+#include
+
#include "OEMCryptoCENCCommon.h"
#include "gtest/gtest.h"
#include "odk.h"
@@ -35,7 +38,7 @@ TEST(OdkTimerBasicTest, ParseLicenseTimerSet) {
// playback timer is successfully started
::wvodk_test::ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
- params.parsed_license.renewal_delay_base = OEMCrypto_License_Load;
+ params.parsed_license.renewal_delay_base = OEMCrypto_LicenseLoad;
params.parsed_license.timer_limits.soft_enforce_rental_duration = false;
params.parsed_license.timer_limits.soft_enforce_playback_duration = false;
params.parsed_license.timer_limits.earliest_playback_start_seconds = 10;
@@ -46,47 +49,41 @@ TEST(OdkTimerBasicTest, ParseLicenseTimerSet) {
ODK_InitializeClockValues(¶ms.clock_values, kSystemTime);
EXPECT_EQ(OEMCrypto_SUCCESS, result);
params.clock_values.time_of_license_request_signed = 5;
- params.clock_values.status = kActive;
+ params.clock_values.status = OEMCrypto_Active;
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
result = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, kSystemTime, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, kSystemTime,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_SET_TIMER, result);
- delete[] buf;
}
TEST(OdkTimerBasicTest, ParseLicenseTimerDisabled) {
// playback timer is successfully started
::wvodk_test::ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
- params.parsed_license.renewal_delay_base = OEMCrypto_License_Load;
+ params.parsed_license.renewal_delay_base = OEMCrypto_LicenseLoad;
params.parsed_license.timer_limits.soft_enforce_rental_duration = true;
params.parsed_license.timer_limits.earliest_playback_start_seconds = 3;
params.parsed_license.timer_limits.total_playback_duration_seconds = 0;
params.parsed_license.timer_limits.initial_renewal_duration_seconds = 0;
params.clock_values.time_of_first_decrypt = 10;
params.clock_values.time_of_license_request_signed = 5;
- params.clock_values.status = kActive;
+ params.clock_values.status = OEMCrypto_Active;
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
OEMCryptoResult result = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, kSystemTime, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, kSystemTime,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_DISABLE_TIMER, result);
- delete[] buf;
}
TEST(OdkTimerBasicTest, ParseRenewalTimerExpired) {
@@ -94,7 +91,7 @@ TEST(OdkTimerBasicTest, ParseRenewalTimerExpired) {
::wvodk_test::ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
- params.parsed_license.renewal_delay_base = OEMCrypto_License_Load;
+ params.parsed_license.renewal_delay_base = OEMCrypto_LicenseLoad;
params.parsed_license.timer_limits.rental_duration_seconds = 5;
params.parsed_license.timer_limits.earliest_playback_start_seconds = 3;
OEMCryptoResult result =
@@ -102,18 +99,15 @@ TEST(OdkTimerBasicTest, ParseRenewalTimerExpired) {
EXPECT_EQ(OEMCrypto_SUCCESS, result);
params.clock_values.time_of_license_request_signed = 5;
- uint8_t* buf = nullptr;
- uint32_t buf_size = 0;
- ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
- &buf_size);
+ std::vector buf;
+ ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
result = ODK_ParseLicense(
- buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
- params.usage_entry_present, kSystemTime, &(params.timer_limits),
- &(params.clock_values), &(params.core_message.nonce_values),
- &(params.parsed_license), nullptr);
+ buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
+ params.initial_license_load, params.usage_entry_present, kSystemTime,
+ &(params.timer_limits), &(params.clock_values),
+ &(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_TIMER_EXPIRED, result);
- delete[] buf;
}
} // namespace wvodk_test
@@ -121,7 +115,7 @@ TEST(OdkTimerBasicTest, ParseRenewalTimerExpired) {
TEST(OdkTimerBasicTest, NullTest) {
// Assert that nullptr does not cause a core dump.
ODK_InitializeClockValues(nullptr, 0u);
- ODK_ReloadClockValues(nullptr, 0u, 0u, 0u, kActive, 0u);
+ ODK_ReloadClockValues(nullptr, 0u, 0u, 0u, OEMCrypto_Active, 0u);
ODK_AttemptFirstPlayback(0u, nullptr, nullptr, nullptr);
ODK_UpdateLastPlaybackTime(0, nullptr, nullptr);
ASSERT_TRUE(true);
@@ -139,7 +133,7 @@ TEST(OdkTimerBasicTest, Init) {
EXPECT_EQ(clock_values.time_when_timer_expires, 0u);
EXPECT_EQ(clock_values.timer_status,
ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED);
- EXPECT_EQ(clock_values.status, kUnused);
+ EXPECT_EQ(clock_values.status, OEMCrypto_Unused);
}
TEST(OdkTimerBasicTest, Reload) {
@@ -151,7 +145,7 @@ TEST(OdkTimerBasicTest, Reload) {
uint64_t lic_signed = 1u;
uint64_t first_decrypt = 2u;
uint64_t last_decrypt = 3u;
- enum OEMCrypto_Usage_Entry_Status status = kInactiveUsed;
+ enum OEMCrypto_UsageEntryStatus status = OEMCrypto_InactiveUsed;
ODK_ReloadClockValues(&clock_values, lic_signed, first_decrypt, last_decrypt,
status, time);
EXPECT_EQ(clock_values.time_of_license_request_signed, lic_signed);
@@ -247,7 +241,7 @@ class ODKTimerTest : public ::testing::Test {
const OEMCryptoResult result = ODK_AttemptFirstPlayback(
start, &timer_limits_, &clock_values_, &timer_value);
// After first playback, the license is active.
- EXPECT_EQ(clock_values_.status, kActive);
+ EXPECT_EQ(clock_values_.status, OEMCrypto_Active);
EXPECT_EQ(clock_values_.time_when_timer_expires, cutoff);
if (cutoff > 0) { // If we expect the timer to be set.
EXPECT_EQ(result, ODK_SET_TIMER);
@@ -324,7 +318,7 @@ class ODKTimerTest : public ::testing::Test {
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_last_decrypt, time_of_last_decrypt);
- EXPECT_EQ(clock_values_.status, kActive);
+ EXPECT_EQ(clock_values_.status, OEMCrypto_Active);
}
// Convert from rental time to system time. By "system time", we mean
@@ -369,7 +363,7 @@ TEST_F(ODKTimerTest, EarlyTest) {
// We use the TIMER_EXPIRED error to mean both early or late.
ForbidPlayback(bad_start_time);
// And times were not updated:
- EXPECT_EQ(clock_values_.status, kUnused);
+ EXPECT_EQ(clock_values_.status, OEMCrypto_Unused);
// This is when we will attempt the first valid playback.
start_of_playback_ =
GetSystemTime(timer_limits_.earliest_playback_start_seconds + 10);
@@ -928,7 +922,7 @@ class RenewalTest : public ODKTimerTest {
&timer_limits_, &clock_values_, start, renewal_duration_seconds,
timer_value_pointer);
// After first playback, the license is active.
- EXPECT_EQ(clock_values_.status, kActive);
+ EXPECT_EQ(clock_values_.status, OEMCrypto_Active);
EXPECT_EQ(clock_values_.time_when_timer_expires, cutoff);
if (cutoff > 0) { // If we expect the timer to be set.
EXPECT_EQ(result, ODK_SET_TIMER);
diff --git a/oemcrypto/oemcrypto_security_tests.gyp b/oemcrypto/oemcrypto_security_tests.gyp
index 98feb27..6deb671 100644
--- a/oemcrypto/oemcrypto_security_tests.gyp
+++ b/oemcrypto/oemcrypto_security_tests.gyp
@@ -29,15 +29,14 @@
'<(platform_specific_dir)/log.cpp',
'<(util_dir)/src/cdm_random.cpp',
'<(util_dir)/src/platform.cpp',
- '<(util_dir)/src/rw_lock.cpp',
'<(util_dir)/src/string_conversions.cpp',
+ '<(util_dir)/src/string_utils.cpp',
'<(util_dir)/test/test_sleep.cpp',
'<(util_dir)/test/test_clock.cpp',
],
'includes': [
'../util/libssl_dependency.gypi',
'test/oemcrypto_security_tests.gypi',
- 'util/oec_ref_util.gypi',
'util/oec_ref_util_unittests.gypi',
],
'libraries': [
@@ -46,6 +45,8 @@
'dependencies': [
'<(gtest_dependency)',
'<(gmock_dependency)',
+ '<(oemcrypto_dir)/util/wvcrc32.gyp:libwvcrc32',
+ '<(oemcrypto_dir)/util/build.gyp:liboec_ref_util',
],
},
],
diff --git a/oemcrypto/oemcrypto_unittests.gyp b/oemcrypto/oemcrypto_unittests.gyp
index 3985423..83eddf7 100644
--- a/oemcrypto/oemcrypto_unittests.gyp
+++ b/oemcrypto/oemcrypto_unittests.gyp
@@ -17,8 +17,6 @@
'platform_specific_dir': 'drm_private_key->signature_size;
result = ODK_PrepareCoreLicenseRequest(
message, message_length, core_message_length,
- &session_context->nonce_values, &g_counter_info);
+ &session_context->nonce_values, &g_counter_info, 0);
if (*signature_length < required_signature_size ||
result == OEMCrypto_ERROR_SHORT_BUFFER) {
*signature_length = required_signature_size;
/* The core_message_length has been correctly set by
- * ODK_PrepareCoreLicenseRequest, but the message and signature buffer will
- * be initialized and filled in the subsequent call. */
+ * ODK_PrepareCoreLicenseRequest, but the message and signature buffer
+ * will be initialized and filled in the subsequent call. */
return OEMCrypto_ERROR_SHORT_BUFFER;
}
if (result != OEMCrypto_SUCCESS) {
@@ -1076,8 +1077,8 @@ OEMCryptoResult OEMCrypto_PrepAndSignLicenseRequest(
message_or_hash_length = sizeof(message_hash);
}
- /* For backwards compatibility, we only sign the message body, and we compute
- * a SHA256 of the core message. */
+ /* For backwards compatibility, we only sign the message body, and we
+ * compute a SHA256 of the core message. */
result = WTPI_C1_SHA256(message, *core_message_length,
session_context->license_request_hash);
if (result != OEMCrypto_SUCCESS) {
@@ -1130,8 +1131,9 @@ OEMCryptoResult OEMCrypto_PrepAndSignReleaseRequest(
}
ABORT_IF(session_context == NULL,
"OPKI_GetSession() provided invalid output.");
- // If we are talking to an old license server, then call the renewal function.
- if (session_context->nonce_values.api_major_version < 19) {
+ // If we are talking to an old license server, then call the renewal
+ // function.
+ if (session_context->nonce_values.api_major_version < 20) {
return OEMCrypto_PrepAndSignRenewalRequest(session, message, message_length,
core_message_length, signature,
signature_length);
@@ -1141,9 +1143,10 @@ OEMCryptoResult OEMCrypto_PrepAndSignReleaseRequest(
if (result != OEMCrypto_SUCCESS) return result;
RETURN_INVALID_CONTEXT_IF_NULL(core_message_length);
RETURN_INVALID_CONTEXT_IF_NULL(signature_length);
- /* If we have signed a request, but have not loaded it, something is wrong. On
- * the other hand, we can sign a license release using the mac keys from the
- * usage table. So it is OK if we have never signed a license request. */
+ /* If we have signed a request, but have not loaded it, something is wrong.
+ * On the other hand, we can sign a license release using the mac keys from
+ * the usage table. So it is OK if we have never signed a license request.
+ */
if (session_context->request_signed && !session_context->response_loaded) {
LOGE("Attempt to sign release before load");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1166,12 +1169,14 @@ OEMCryptoResult OEMCrypto_PrepAndSignReleaseRequest(
return result;
}
- OEMCrypto_Usage_Entry_Status status;
+ OEMCrypto_UsageEntryStatus status;
int64_t seconds_since_license_received;
int64_t seconds_since_first_decrypt;
- result = OPKI_GetUsageEntryInfo(session_context->session_id, &status,
- &seconds_since_license_received,
- &seconds_since_first_decrypt);
+ uint8_t pst[ODK_PST_LEN_MAX];
+ size_t pst_length = sizeof(pst);
+ result = OPKI_GetUsageEntryInfo(
+ session_context->session_id, &status, &seconds_since_license_received,
+ &seconds_since_first_decrypt, pst, &pst_length);
if (result != OEMCrypto_SUCCESS) {
LOGE("Error with getting usage entry info");
return result;
@@ -1179,15 +1184,15 @@ OEMCryptoResult OEMCrypto_PrepAndSignReleaseRequest(
result = ODK_PrepareCoreReleaseRequest(
message, message_length, core_message_length,
- &session_context->nonce_values, status, kMonotonicClock,
- seconds_since_license_received, seconds_since_first_decrypt,
- &session_context->clock_values, now);
+ &session_context->nonce_values, status, OEMCrypto_MonotonicClock,
+ seconds_since_license_received, seconds_since_first_decrypt, pst,
+ pst_length, &session_context->clock_values, now);
if (*signature_length < required_signature_size ||
result == OEMCrypto_ERROR_SHORT_BUFFER) {
*signature_length = required_signature_size;
/* The core_message_length has been correctly set by
- * ODK_PrepareCoreReleaseRequest, but the message and signature buffer will
- * be initialized and filled in the subsequent call. */
+ * ODK_PrepareCoreReleaseRequest, but the message and signature buffer
+ * will be initialized and filled in the subsequent call. */
return OEMCrypto_ERROR_SHORT_BUFFER;
}
if (result != OEMCrypto_SUCCESS) {
@@ -1251,9 +1256,10 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
if (result != OEMCrypto_SUCCESS) return result;
RETURN_INVALID_CONTEXT_IF_NULL(core_message_length);
RETURN_INVALID_CONTEXT_IF_NULL(signature_length);
- /* If we have signed a request, but have not loaded it, something is wrong. On
- * the other hand, we can sign a license release using the mac keys from the
- * usage table. So it is OK if we have never signed a license request. */
+ /* If we have signed a request, but have not loaded it, something is wrong.
+ * On the other hand, we can sign a license release using the mac keys from
+ * the usage table. So it is OK if we have never signed a license request.
+ */
if (session_context->request_signed && !session_context->response_loaded) {
LOGE("Attempt to sign renewal before load");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1269,8 +1275,8 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
result == OEMCrypto_ERROR_SHORT_BUFFER) {
*signature_length = required_signature_size;
/* The core_message_length has been correctly set by
- * ODK_PrepareCoreRenewalRequest, but the message and signature buffer will
- * be initialized and filled in the subsequent call. */
+ * ODK_PrepareCoreRenewalRequest, but the message and signature buffer
+ * will be initialized and filled in the subsequent call. */
return OEMCrypto_ERROR_SHORT_BUFFER;
}
if (result != OEMCrypto_SUCCESS) {
@@ -1285,8 +1291,8 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
}
RETURN_INVALID_CONTEXT_IF_NULL(signature);
if (session_context->nonce_values.api_major_version < ODK_FIRST_VERSION) {
- /* If we are talking to an old license server, then we only sign the message
- * body. */
+ /* If we are talking to an old license server, then we only sign the
+ * message body. */
const uint8_t* message_body = message + *core_message_length;
const size_t message_body_length = message_length - *core_message_length;
if (OPKI_CheckKey(session_context->mac_key_client, MAC_KEY_CLIENT)) {
@@ -1328,7 +1334,7 @@ OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
static OEMCryptoResult LoadKeysNoSignature(
OEMCryptoSession* session, const uint8_t* message, size_t message_length,
OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys,
- size_t num_keys, const OEMCrypto_KeyObject* key_array,
+ size_t num_keys, const OEMCrypto_KeyObjectV2* key_array,
OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data,
OEMCrypto_LicenseType license_type) {
ABORT_IF(g_opk_system_state != SYSTEM_INITIALIZED,
@@ -1376,8 +1382,8 @@ static OEMCryptoResult LoadKeysNoSignature(
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
- /* Check to see if the MAC Keys' IV is directly before the MAC Keys, which is
- forbidden. */
+ /* Check to see if the MAC Keys' IV is directly before the MAC Keys, which
+ is forbidden. */
if (enc_mac_keys.offset >= KEY_IV_SIZE && enc_mac_keys.length > 0 &&
crypto_memcmp(message + enc_mac_keys.offset - KEY_IV_SIZE,
message + enc_mac_keys_iv.offset, KEY_IV_SIZE) == 0) {
@@ -1385,12 +1391,13 @@ static OEMCryptoResult LoadKeysNoSignature(
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
- /* If we've already loaded in a license and it isn't the current license type,
- fail. */
+ /* If we've already loaded in a license and it isn't the current license
+ type, fail. */
if (session->state == SESSION_LICENSE_LOADED &&
session->license_type != license_type) {
LOGE(
- "License type doesn't match. License type already loaded: %u, license "
+ "License type doesn't match. License type already loaded: %u, "
+ "license "
"type to be loaded: %u",
session->license_type, license_type);
return OEMCrypto_ERROR_INVALID_CONTEXT;
@@ -1517,7 +1524,8 @@ static OEMCryptoResult LoadKeysNoSignature(
message + pst.offset, pst.length);
if (result != OEMCrypto_SUCCESS) {
LOGE(
- "Failed to verify usage entry PST with result: %u, session_id = "
+ "Failed to verify usage entry PST with result: %u, session_id "
+ "= "
"%u",
result, session->session_id);
break;
@@ -1721,15 +1729,16 @@ OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
goto cleanup;
}
- /* Initialized the index to which the entitled content key to be loaded. */
+ /* Initialized the index to which the entitled content key to be loaded.
+ */
uint32_t entitled_content_key_index =
key_session->num_entitled_content_keys;
- /* It prefers to reuse an existing content key index that is entitled by the
- * same entitlement key if one exists already, but will allocate a new index
- * if there are none that can be reused.
- * The block below searches whether there is an existing content key
- * entitled by the same entitlement key, and will reuse the index to load
- * the new content key if there is one. */
+ /* It prefers to reuse an existing content key index that is entitled by
+ * the same entitlement key if one exists already, but will allocate a new
+ * index if there are none that can be reused. The block below searches
+ * whether there is an existing content key entitled by the same
+ * entitlement key, and will reuse the index to load the new content key
+ * if there is one. */
for (uint32_t k = 0; k < key_session->num_entitled_content_keys; k++) {
/* Gets the entitlement key of the entitled content key at index k. */
const EntitlementKeyInfo* key_info = &key_session->entitlement_keys[k];
@@ -1749,8 +1758,8 @@ OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
}
}
- /* If we're not updating an existing content key and we can't add any more,
- we fail. */
+ /* If we're not updating an existing content key and we can't add any
+ more, we fail. */
const bool adding_new_content_key =
entitled_content_key_index == key_session->num_entitled_content_keys;
if (adding_new_content_key &&
@@ -2260,7 +2269,8 @@ OEMCryptoResult OEMCrypto_Generic_Encrypt(
}
if (in_buffer_length % AES_BLOCK_SIZE != 0) {
LOGE(
- "in_buffer_length of %zu is not a multiple of the crypto block length.",
+ "in_buffer_length of %zu is not a multiple of the crypto block "
+ "length.",
in_buffer_length);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -2337,7 +2347,8 @@ OEMCryptoResult OEMCrypto_Generic_Decrypt(
}
if (in_buffer_length % AES_BLOCK_SIZE != 0) {
LOGE(
- "in_buffer_length of %zu is not a multiple of the crypto block length.",
+ "in_buffer_length of %zu is not a multiple of the crypto block "
+ "length.",
in_buffer_length);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -2649,8 +2660,8 @@ OEMCryptoResult OEMCrypto_FactoryInstallBCCSignature(const uint8_t* signature,
// keybox_CA_token(uint8_t[], 72 bytes) ||
// signature_length(uint32_t, 4 bytes, value=0x20) ||
// signature(uint8_t[], 32 bytes)
- // This signature excluding the leading byte of |signature_type| is generated
- // by OEMCrypto_GetBootCertificateChain() in the factory.
+ // This signature excluding the leading byte of |signature_type| is
+ // generated by OEMCrypto_GetBootCertificateChain() in the factory.
# define SIGNATURE_BY_KEYBOX_MAX_LENGTH 128
if (sizeof(uint8_t) + signature_length > SIGNATURE_BY_KEYBOX_MAX_LENGTH) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
@@ -2806,14 +2817,21 @@ OEMCryptoResult OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) {
return OPKI_SetStatePostCall(session_context, API_LOADOEMPRIVATEKEY);
}
-OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength) {
+OEMCryptoResult OEMCrypto_GetRandom(OEMCrypto_SharedMemory* random_data,
+ size_t random_data_length) {
+#ifdef FACTORY_BUILD_ONLY
if (g_opk_system_state != SYSTEM_INITIALIZED) {
LOGE("OEMCrypto is not yet initialized");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
- RETURN_INVALID_CONTEXT_IF_NULL(randomData);
- RETURN_INVALID_CONTEXT_IF_ZERO(dataLength);
- return WTPI_C1_RandomBytes(randomData, dataLength);
+ RETURN_INVALID_CONTEXT_IF_NULL(random_data);
+ RETURN_INVALID_CONTEXT_IF_ZERO(random_data_length);
+ return WTPI_C1_RandomBytes(random_data, random_data_length);
+#else
+ (void)random_data;
+ (void)random_data_length;
+ return OEMCrypto_ERROR_NOT_IMPLEMENTED;
+#endif
}
uint32_t OEMCrypto_APIVersion(void) { return API_MAJOR_VERSION; }
@@ -3643,7 +3661,7 @@ OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
}
OEMCryptoResult OEMCrypto_GetUsageEntryInfo(
- OEMCrypto_SESSION session, OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_SESSION session, OEMCrypto_UsageEntryStatus* status,
int64_t* seconds_since_license_received,
int64_t* seconds_since_first_decrypt) {
if (g_opk_system_state != SYSTEM_INITIALIZED) {
@@ -3666,9 +3684,11 @@ OEMCryptoResult OEMCrypto_GetUsageEntryInfo(
result = OPKI_CheckStatePreCall(session_context, API_GETUSAGEENTRYINFO);
if (result != OEMCrypto_SUCCESS) return result;
- result = OPKI_GetUsageEntryInfo(session_context->session_id, status,
- seconds_since_license_received,
- seconds_since_first_decrypt);
+ uint8_t pst[ODK_PST_LEN_MAX];
+ size_t pst_length = sizeof(pst);
+ result = OPKI_GetUsageEntryInfo(
+ session_context->session_id, status, seconds_since_license_received,
+ seconds_since_first_decrypt, pst, &pst_length);
if (result != OEMCrypto_SUCCESS) {
LOGE("Failed to get usage entry info with result: %u, session_id = %u",
result, session_context->session_id);
@@ -4000,28 +4020,14 @@ OEMCryptoResult OEMCrypto_GenerateCertificateKeyPair(
/* Generate the key pair and fill the key type. */
size_t required_signature_size = MAX_ASYMMETRIC_SIGNATURE_SIZE;
- if (session_context->prov40_oem_private_key == NULL) {
- /* This is for obtaining an OEM leaf cert. The signature is a COSE_SIGN1
- * format. Adjust the required signature size. */
- result = WTPI_GetMaxBccKeyCoseSign1Size(&required_signature_size);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to get max COSE_SIGN1 size: %u", result);
- return result;
- }
+ result = WTPI_GetMaxBccKeyCoseSign1Size(&required_signature_size);
+ if (result != OEMCrypto_SUCCESS) {
+ LOGE("Failed to get max COSE_SIGN1 size: %u", result);
+ return result;
}
-
- // Determine which stage of Prov 4 provisioning we are in
- // Stage 1: OEM private key is NOT installed, we are requesting it.
- // Stage 2: OEM private key is installed, now requesting DRM cert.
- const bool is_stage1 = (session_context->prov40_oem_private_key == NULL);
- const CertSignatureType requested_cert_type =
- is_stage1 ? CERT_SIGNATURE_OEM : CERT_SIGNATURE_DRM;
- const uint32_t wrapping_context =
- is_stage1 ? DEVICE_KEY_WRAP_OEM_CERT : DEVICE_KEY_WRAP_DRM_CERT;
-
AsymmetricKeyType generated_key_type;
result = WTPI_GenerateRandomCertificateKeyPair(
- requested_cert_type, &generated_key_type, wrapped_private_key,
+ CERT_SIGNATURE_DRM, &generated_key_type, wrapped_private_key,
wrapped_private_key_size, public_key, public_key_size);
if (public_key_signature == NULL ||
*public_key_signature_size < required_signature_size ||
@@ -4041,65 +4047,19 @@ OEMCryptoResult OEMCrypto_GenerateCertificateKeyPair(
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
- if (is_stage1) {
- /* This is the first stage for obtaining an OEM leaf cert. Sign with BCC
- * leaf private key. */
- result =
- WTPI_BccKeyCoseSign1(public_key, *public_key_size, public_key_signature,
- public_key_signature_size);
- } else {
- /* This is the second stage for obtaining a DRM cert. Sign with the
- * installed prov40_oem_private_key. */
- WTPI_AsymmetricKey_Handle signing_key_handle;
- uint32_t allowed_schemes_unused;
- AsymmetricKey* oem_private_key = session_context->prov40_oem_private_key;
- result = WTPI_UnwrapIntoAsymmetricKeyHandle(
- DEVICE_KEY_WRAP_OEM_CERT, oem_private_key->wrapped_key,
- oem_private_key->wrapped_key_length, oem_private_key->key_type,
- &signing_key_handle, &allowed_schemes_unused);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to unwrap OEM private key into key handle with result: %u",
- result);
- return result;
- }
- /* Sign the generated public key. */
- switch (oem_private_key->key_type) {
- case DRM_ECC_PRIVATE_KEY: {
- result = WTPI_ECCSign(signing_key_handle, public_key, *public_key_size,
- public_key_signature, public_key_signature_size);
- break;
- }
- case DRM_RSA_PRIVATE_KEY: {
- /* If the signing key is RSA, the signing key must be OEM private key.
- */
- if ((session_context->prov40_oem_allowed_schemes & kSign_RSASSA_PSS) !=
- kSign_RSASSA_PSS) {
- LOGE("Bad prov40 OEM RSA padding scheme: %x",
- session_context->prov40_oem_allowed_schemes);
- result = OEMCrypto_ERROR_INVALID_KEY;
- break;
- }
- result = WTPI_RSASign(signing_key_handle, public_key, *public_key_size,
- public_key_signature, public_key_signature_size,
- kSign_RSASSA_PSS);
- break;
- }
- case PROV40_ED25519_PRIVATE_KEY:
- default:
- LOGE("Unexpected signing private key type");
- result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
- break;
- }
- WTPI_FreeAsymmetricKeyHandle(signing_key_handle);
- }
+ /* Sign the generated public key with the BCC leaf private key. */
+ result =
+ WTPI_BccKeyCoseSign1(public_key, *public_key_size, public_key_signature,
+ public_key_signature_size);
if (result != OEMCrypto_SUCCESS) {
return result;
}
+
/* Store the generated key for signing the provisioning request. */
WTPI_AsymmetricKey_Handle csr_signing_key_handle;
uint32_t allowed_schemes;
result = WTPI_UnwrapIntoAsymmetricKeyHandle(
- wrapping_context, wrapped_private_key, *wrapped_private_key_size,
+ DEVICE_KEY_WRAP_DRM_CERT, wrapped_private_key, *wrapped_private_key_size,
generated_key_type, &csr_signing_key_handle, &allowed_schemes);
if (result != OEMCrypto_SUCCESS) {
LOGE(
@@ -4131,7 +4091,7 @@ OEMCryptoResult OEMCrypto_GenerateCertificateKeyPair(
LOGE("Failed to create asymmetric CSR signing key with result: %u", result);
return result;
}
- session_context->prov40_csr_keywrap_context = wrapping_context;
+
return OPKI_SetStatePostCall(session_context, API_GENERATECERTIFICATEKEYPAIR);
}
@@ -4206,67 +4166,13 @@ OEMCryptoResult OEMCrypto_GetDeviceSignedCsrPayload(
OEMCryptoResult OEMCrypto_InstallOemPrivateKey(
OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
const uint8_t* wrapped_private_key, size_t wrapped_private_key_length) {
- RETURN_INVALID_CONTEXT_IF_NULL(wrapped_private_key);
- if (g_opk_system_state != SYSTEM_INITIALIZED) {
- LOGE("OEMCrypto is not yet initialized");
- return OEMCrypto_ERROR_UNKNOWN_FAILURE;
- }
- AsymmetricKeyType oem_key_type;
- if (!OPKI_PrivateKeyTypeToAsymmetricKey(key_type, &oem_key_type)) {
- LOGE("Invalid key_type: %d", key_type);
- return OEMCrypto_ERROR_INVALID_CONTEXT;
- }
- if (OPKI_GetSessionType(session) != SESSION_TYPE_OEMCRYPTO) {
- LOGE("Unexpected session type.");
- return OEMCrypto_ERROR_INVALID_SESSION;
- }
- OEMCryptoSession* session_context = NULL;
- OEMCryptoResult result = OPKI_GetSession(session, &session_context);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to get session with result: %u, session = %u", result,
- session);
- return result;
- }
- ABORT_IF(session_context == NULL,
- "OPKI_GetSession() provided invalid output.");
- result = OPKI_CheckStatePreCall(session_context, API_INSTALLOEMPRIVATEKEY);
- if (result != OEMCrypto_SUCCESS) return result;
-
- WTPI_AsymmetricKey_Handle private_key_handle;
- uint32_t allowed_schemes;
- result = WTPI_UnwrapIntoAsymmetricKeyHandle(
- DEVICE_KEY_WRAP_OEM_CERT, wrapped_private_key, wrapped_private_key_length,
- oem_key_type, &private_key_handle, &allowed_schemes);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to unwrap OEM private key into key handle with result: %u",
- result);
- return result;
- }
- size_t signature_size;
- result = WTPI_GetSignatureSize(private_key_handle, &signature_size);
- WTPI_FreeAsymmetricKeyHandle(private_key_handle);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to get OEM key signature size with result: %u", result);
- return result;
- }
-
- result = OPKI_LoadProv40OEMKey(
- session_context, oem_key_type, wrapped_private_key,
- wrapped_private_key_length, signature_size, allowed_schemes);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to install OEM key");
- goto cleanup;
- }
- result = OPKI_SetStatePostCall(session_context, API_INSTALLOEMPRIVATEKEY);
-
-cleanup:;
- OEMCryptoResult free_key_result = FreeMacAndEncryptionKeys(session_context);
- if (result == OEMCrypto_SUCCESS) result = free_key_result;
- if (result != OEMCrypto_SUCCESS) {
- OPKI_FreeAsymmetricKeyFromTable(&session_context->prov40_oem_private_key);
- session_context->state = SESSION_INVALID;
- }
- return result;
+ // TODO(b/374834498): Remove stub once build system is updated to
+ // handle backwards-compatible OEMCrypto testing.
+ (void)session;
+ (void)key_type;
+ (void)wrapped_private_key;
+ (void)wrapped_private_key_length;
+ return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
OEMCryptoResult OEMCrypto_ReassociateEntitledKeySession(
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h b/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h
index fec38f8..597ed6d 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_api_macros.h
@@ -33,9 +33,9 @@
// OEMCrypto API version would be v17.0.1; once the supported OEMCrypto API
// version bumps to v17.1, the first released OPK implementation would be
// v17.1.0
-#define API_MAJOR_VERSION 19
-#define API_MINOR_VERSION 5
+#define API_MAJOR_VERSION 20
+#define API_MINOR_VERSION 0
#define OPK_PATCH_VERSION 0
-#define OPK_BUILD_ID "19.5.0"
+#define OPK_BUILD_ID "MAIN"
#endif /* OEMCRYPTO_TA_OEMCRYPTO_API_MACROS_H_ */
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_key.c b/oemcrypto/opk/oemcrypto_ta/oemcrypto_key.c
index b71b264..2cd3675 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_key.c
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_key.c
@@ -71,10 +71,10 @@ bool OPKI_PrivateKeyTypeToAsymmetricKey(OEMCrypto_PrivateKeyType priv_key_type,
AsymmetricKeyType* asym_key_type) {
if (asym_key_type == NULL) return false;
switch (priv_key_type) {
- case OEMCrypto_RSA_Private_Key:
+ case OEMCrypto_RSAPrivateKey:
*asym_key_type = DRM_RSA_PRIVATE_KEY;
return true;
- case OEMCrypto_ECC_Private_Key:
+ case OEMCrypto_ECCPrivateKey:
*asym_key_type = DRM_ECC_PRIVATE_KEY;
return true;
}
@@ -86,10 +86,10 @@ bool OPKI_AsymmetricKeyToPrivateKeyType(
if (priv_key_type == NULL) return false;
switch (asym_key_type) {
case DRM_RSA_PRIVATE_KEY:
- *priv_key_type = OEMCrypto_RSA_Private_Key;
+ *priv_key_type = OEMCrypto_RSAPrivateKey;
return true;
case DRM_ECC_PRIVATE_KEY:
- *priv_key_type = OEMCrypto_ECC_Private_Key;
+ *priv_key_type = OEMCrypto_ECCPrivateKey;
return true;
case PROV40_ED25519_PRIVATE_KEY:
// ED25519 key can only be used in provisioning 4 BCC.
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_key_control_block.c b/oemcrypto/opk/oemcrypto_ta/oemcrypto_key_control_block.c
index 5725dc1..07fbcf2 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_key_control_block.c
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_key_control_block.c
@@ -32,6 +32,7 @@ OEMCryptoResult OPKI_ParseKeyControlBlock(const uint8_t* kcb,
const char* verification = key_control_block.verification;
key_control_block.valid =
+ memcmp(verification, "kc20", 4) == 0 || /* add in version 20 api */
memcmp(verification, "kc19", 4) == 0 || /* add in version 19 api */
memcmp(verification, "kc18", 4) == 0 || /* add in version 18 api */
memcmp(verification, "kc17", 4) == 0 || /* add in version 17 api */
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_serialized_usage_table.h b/oemcrypto/opk/oemcrypto_ta/oemcrypto_serialized_usage_table.h
index f606d7e..3e135c3 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_serialized_usage_table.h
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_serialized_usage_table.h
@@ -50,7 +50,7 @@ typedef struct SavedUsageEntry {
int64_t time_of_first_decrypt; /* Time in seconds on system clock. */
int64_t time_of_last_decrypt; /* Time in seconds on system clock.. */
/* Status of the entry or license, as documented in OEMCrypto spec. */
- enum OEMCrypto_Usage_Entry_Status status;
+ enum OEMCrypto_UsageEntryStatus status;
/* Server Mac key wrapped for this device. */
uint8_t mac_key_server[WRAPPED_MAC_KEY_SIZE];
/* Client Mac key wrapped for this device. */
@@ -117,7 +117,7 @@ typedef struct SavedUsageEntryLegacy {
int64_t time_of_first_decrypt; /* Time in seconds on system clock. */
int64_t time_of_last_decrypt; /* Time in seconds on system clock.. */
/* Status of the entry or license, as documented in OEMCrypto spec. */
- enum OEMCrypto_Usage_Entry_Status status;
+ enum OEMCrypto_UsageEntryStatus status;
/* Server Mac key wrapped for this device. */
uint8_t mac_key_server[WRAPPED_MAC_KEY_SIZE];
/* Client Mac key wrapped for this device. */
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.c b/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.c
index d77336c..4f2c886 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.c
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.c
@@ -57,7 +57,6 @@ OEMCryptoResult OPKI_InitializeSession(OEMCryptoSession* session,
.hash_error = OEMCrypto_SUCCESS,
},
.allowed_schemes = kSign_RSASSA_PSS,
- .prov40_oem_allowed_schemes = kSign_RSASSA_PSS,
};
OEMCryptoResult result = ODK_InitializeSessionValues(
&session->timer_limits, &session->clock_values, &session->nonce_values,
@@ -72,10 +71,6 @@ OEMCryptoResult OPKI_TerminateSession(OEMCryptoSession* session) {
OPKI_FreeAsymmetricKeyFromTable(&session->drm_private_key);
OEMCryptoResult result = free_key_result;
- free_key_result =
- OPKI_FreeAsymmetricKeyFromTable(&session->prov40_oem_private_key);
- if (result == OEMCrypto_SUCCESS) result = free_key_result;
-
free_key_result =
OPKI_FreeAsymmetricKeyFromTable(&session->prov40_csr_signing_key);
if (result == OEMCrypto_SUCCESS) result = free_key_result;
@@ -122,7 +117,6 @@ OEMCryptoResult OPKI_CheckStatePreCall(OEMCryptoSession* session,
switch (session->state) {
case (SESSION_OPENED):
case (SESSION_LOAD_OEM_RSA_KEY):
- case (SESSION_PROV4_OEM_KEY_LOADED):
case (SESSION_DRM_KEY_LOADED):
case (SESSION_CAST_RSA_KEY_LOADED):
return OEMCrypto_SUCCESS;
@@ -142,7 +136,6 @@ OEMCryptoResult OPKI_CheckStatePreCall(OEMCryptoSession* session,
switch (session->state) {
case (SESSION_OPENED):
case (SESSION_LOAD_OEM_RSA_KEY):
- case (SESSION_PROV4_OEM_KEY_LOADED):
case (SESSION_PREPARING_REQUEST):
case (SESSION_DRM_KEY_LOADED):
case (SESSION_CAST_RSA_KEY_LOADED):
@@ -190,8 +183,6 @@ OEMCryptoResult OPKI_CheckStatePreCall(OEMCryptoSession* session,
case (SESSION_OPENED):
case (SESSION_PREPARING_REQUEST):
case (SESSION_USAGE_ENTRY_LOADED):
- // Prov 4 OEM private key installed at beginning of session
- case (SESSION_PROV4_OEM_KEY_LOADED):
// Provisioning 4 skips LoadProvisioning
case (SESSION_WAIT_FOR_PROVISIONING):
// This can happen when using testing the CDM with a pre-provisioned
@@ -203,25 +194,11 @@ OEMCryptoResult OPKI_CheckStatePreCall(OEMCryptoSession* session,
default:
goto err;
}
- case API_INSTALLOEMPRIVATEKEY:
- switch (session->state) {
- case (SESSION_OPENED):
- case (SESSION_PREPARING_REQUEST):
- case (SESSION_USAGE_ENTRY_LOADED):
- // Provisioning 3 calls OEMCrypto_LoadOEMPrivateKey during provisioning
- case (SESSION_LOAD_OEM_RSA_KEY):
- // Provisioning 4 skips LoadProvisioning
- case (SESSION_WAIT_FOR_PROVISIONING):
- return OEMCrypto_SUCCESS;
- default:
- goto err;
- }
case API_GENERATECERTIFICATEKEYPAIR:
switch (session->state) {
case (SESSION_OPENED):
case (SESSION_PREPARING_REQUEST):
case (SESSION_USAGE_ENTRY_LOADED):
- case (SESSION_PROV4_OEM_KEY_LOADED):
return OEMCrypto_SUCCESS;
default:
goto err;
@@ -416,9 +393,6 @@ OEMCryptoResult OPKI_SetStatePostCall(OEMCryptoSession* session,
case API_LOADOEMPRIVATEKEY:
session->state = SESSION_LOAD_OEM_RSA_KEY;
break;
- case API_INSTALLOEMPRIVATEKEY:
- session->state = SESSION_PROV4_OEM_KEY_LOADED;
- break;
case API_DECRYPTCENC:
case API_GENERICENCRYPT:
case API_GENERICDECRYPT:
@@ -496,38 +470,6 @@ OEMCryptoResult OPKI_LoadDRMKey(OEMCryptoSession* session,
return OEMCrypto_SUCCESS;
}
-OEMCryptoResult OPKI_LoadProv40OEMKey(OEMCryptoSession* session,
- AsymmetricKeyType key_type,
- const uint8_t* wrapped_key,
- size_t wrapped_key_length,
- size_t signature_size,
- uint32_t allowed_schemes) {
- if (session == NULL || wrapped_key == NULL || wrapped_key_length == 0 ||
- !IsSupportedDrmKeyType(key_type)) {
- return OEMCrypto_ERROR_INVALID_CONTEXT;
- }
- // Free any existing keys. This will only happen if we are using the test RSA
- // key and then try to load an existing device certificate.
- OEMCryptoResult result =
- OPKI_FreeAsymmetricKeyFromTable(&session->prov40_oem_private_key);
- if (result != OEMCrypto_SUCCESS) return result;
-
- if (key_type != DRM_RSA_PRIVATE_KEY) {
- allowed_schemes = 0;
- }
-
- result = OPKI_CreateAsymmetricKey(&session->prov40_oem_private_key, key_type,
- wrapped_key, wrapped_key_length,
- signature_size, allowed_schemes);
- if (result != OEMCrypto_SUCCESS) {
- LOGE("Failed to create asymmetric OEM private key with result: %u", result);
- return result;
- }
- session->prov40_oem_allowed_schemes = allowed_schemes;
-
- return OEMCrypto_SUCCESS;
-}
-
NO_IGNORE_RESULT static OEMCryptoResult DeriveKey(
WTPI_K1_SymmetricKey_Handle master_key, uint8_t counter,
const uint8_t* key_label, size_t key_label_length, const uint8_t* context,
@@ -665,12 +607,12 @@ OEMCryptoResult OPKI_GenerateCertSignature(OEMCryptoSession* session,
key_type = signing_key->key_type;
wrapping_context = DEVICE_KEY_WRAP_DRM_CERT;
} else if (signature_type == CERT_SIGNATURE_CSR) {
- // Prov40 OEM cert, RSA or ECC
+ // Prov40 CSR signing key (RSA or ECC)
if (!DRMKeyMaySign(session->prov40_csr_signing_key))
return OEMCrypto_ERROR_INVALID_KEY;
signing_key = session->prov40_csr_signing_key;
key_type = signing_key->key_type;
- wrapping_context = session->prov40_csr_keywrap_context;
+ wrapping_context = DEVICE_KEY_WRAP_DRM_CERT;
} else if (signature_type == CERT_SIGNATURE_OEM) {
// Prov30 OEM cert, RSA only
// For Prov30, signing key handle is directly loaded from the secure
@@ -720,12 +662,9 @@ NO_IGNORE_RESULT OEMCryptoResult OPKI_GetSessionSignatureHashAlgorithm(
if (session->drm_private_key != NULL) {
key = session->drm_private_key;
context = DEVICE_KEY_WRAP_DRM_CERT;
- } else if (session->prov40_oem_private_key != NULL) {
- key = session->prov40_oem_private_key;
- context = DEVICE_KEY_WRAP_OEM_CERT;
} else if (session->prov40_csr_signing_key != NULL) {
key = session->prov40_csr_signing_key;
- context = session->prov40_csr_keywrap_context;
+ context = DEVICE_KEY_WRAP_DRM_CERT;
} else if (session->prov30_oem_key_loaded) {
// Create OEM key handle on the fly for prov30 since it is not held by
// the session.
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.h b/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.h
index ea7d57a..a90cb27 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.h
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_session.h
@@ -32,7 +32,6 @@ typedef enum OEMCryptoSessionState {
SESSION_INVALID = (int)0x23a27071,
SESSION_LOAD_OEM_RSA_KEY = (int)0x9d7cae94,
SESSION_DRM_KEY_LOADED = (int)0xbc17f592,
- SESSION_PROV4_OEM_KEY_LOADED = (int)0x902c5b0a,
SESSION_CAST_RSA_KEY_LOADED = (int)0x84a0bb23,
} OEMCryptoSessionState;
@@ -74,7 +73,6 @@ typedef enum OEMCryptoSessionAPI {
API_LOADRENEWAL = (int)0xb096dc9a,
API_LOADRELEASE = (int)0x7b89f4a2,
API_CREATEENTITLEDKEYSESSION = (int)0x6d7d9bfc,
- API_INSTALLOEMPRIVATEKEY = (int)0xd6195c63,
API_GENERATECERTIFICATEKEYPAIR = (int)0x30871a8a,
API_GETKEYHANDLE = (int)0x81aac42f,
} OEMCryptoSessionAPI;
@@ -83,14 +81,8 @@ typedef struct OEMCryptoSession {
OEMCrypto_SESSION session_id;
OEMCryptoSessionState state;
AsymmetricKey* drm_private_key;
- /* This key can only be used to sign the generated cert key in
- * provisioning 4.*/
- AsymmetricKey* prov40_oem_private_key;
- /* This key can only be used to sign the provisioning 4 requests. For stage 1,
- * it is the generated OEM private key. For stage 2, it is the generated DRM
- * private key. */
+ /* This key can only be used to sign the provisioning 4 requests. */
AsymmetricKey* prov40_csr_signing_key;
- uint32_t prov40_csr_keywrap_context;
SymmetricKey* mac_key_server;
SymmetricKey* mac_key_client;
SymmetricKey* encryption_key;
@@ -103,7 +95,6 @@ typedef struct OEMCryptoSession {
bool valid_srm_version;
uint64_t timer_start;
uint32_t allowed_schemes; /* For RSA signatures. */
- uint32_t prov40_oem_allowed_schemes; /* For RSA signatures. */
bool decrypt_started; /* If the license has been used in this session. */
ODK_NonceValues nonce_values;
ODK_TimerLimits timer_limits;
@@ -170,15 +161,6 @@ NO_IGNORE_RESULT OEMCryptoResult OPKI_LoadDRMKey(OEMCryptoSession* session,
size_t signature_size,
uint32_t allowed_schemes);
-/* Attempts to load the wrapped OEM private key |wrapped_key| into |session|'s
- |prov40_oem_private_key| field. |key_type| must be valid. |allowed_schemes|
- is only assigned for key types which support it.
- Caller retains ownership of all pointers and they must not be NULL. */
-NO_IGNORE_RESULT OEMCryptoResult
-OPKI_LoadProv40OEMKey(OEMCryptoSession* session, AsymmetricKeyType key_type,
- const uint8_t* wrapped_key, size_t wrapped_key_length,
- size_t signature_size, uint32_t allowed_schemes);
-
/* Derives mac and encryption keys from the specific key. Uses AES-128-CMAC
and |context| to derive and create a mac_key_server, mac_key_client, and
encryption_key for the |session|.
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.c b/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.c
index 997a5dd..30d1207 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.c
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.c
@@ -97,7 +97,7 @@ static UsageTable g_usage_table;
/* TODO(b/158720996): figure out a way to avoid __attribute__(packed). */
typedef struct {
uint8_t signature[20]; // -- HMAC SHA1 of the rest of the report.
- uint8_t status; // current status of entry. (OEMCrypto_Usage_Entry_Status)
+ uint8_t status; // current status of entry. (OEMCrypto_UsageEntryStatus)
uint8_t clock_security_level;
uint8_t pst_length;
uint8_t padding; // make int64's word aligned.
@@ -624,8 +624,9 @@ OEMCryptoResult OPKI_TerminateUsageTable(void) {
static NO_IGNORE_RESULT UsageEntryStatus
GetUsageEntryStatusFromEntry(UsageEntry* entry) {
ABORT_IF_NULL(entry);
- if (entry->data.status == kInactive || entry->data.status == kInactiveUsed ||
- entry->data.status == kInactiveUnused) {
+ if (entry->data.status == OEMCrypto_Inactive ||
+ entry->data.status == OEMCrypto_InactiveUsed ||
+ entry->data.status == OEMCrypto_InactiveUnused) {
return USAGE_ENTRY_DEACTIVATED;
}
if (entry->is_loaded) {
@@ -1360,12 +1361,15 @@ OEMCryptoResult OPKI_SignReleaseRequest(OEMCrypto_SESSION session_id,
}
OEMCryptoResult OPKI_GetUsageEntryInfo(OEMCrypto_SESSION session_id,
- OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_UsageEntryStatus* status,
int64_t* seconds_since_license_received,
- int64_t* seconds_since_first_decrypt) {
+ int64_t* seconds_since_first_decrypt,
+ uint8_t* pst, size_t* pst_length) {
RETURN_INVALID_CONTEXT_IF_NULL(status);
RETURN_INVALID_CONTEXT_IF_NULL(seconds_since_license_received);
RETURN_INVALID_CONTEXT_IF_NULL(seconds_since_first_decrypt);
+ RETURN_INVALID_CONTEXT_IF_NULL(pst);
+ RETURN_INVALID_CONTEXT_IF_NULL(pst_length);
UsageEntry* entry = FindUsageEntry(session_id);
if (!entry) {
@@ -1373,6 +1377,11 @@ OEMCryptoResult OPKI_GetUsageEntryInfo(OEMCrypto_SESSION session_id,
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
+ if (*pst_length < entry->data.pst_length) {
+ *pst_length = entry->data.pst_length;
+ return OEMCrypto_ERROR_SHORT_BUFFER;
+ }
+
uint64_t now;
OEMCryptoResult result = WTPI_GetTrustedTime(&now);
if (result != OEMCrypto_SUCCESS) {
@@ -1383,6 +1392,8 @@ OEMCryptoResult OPKI_GetUsageEntryInfo(OEMCrypto_SESSION session_id,
*status = entry->data.status;
*seconds_since_license_received = now - entry->data.time_of_license_received;
*seconds_since_first_decrypt = now - entry->data.time_of_first_decrypt;
+ *pst_length = entry->data.pst_length;
+ memcpy(pst, entry->data.pst, entry->data.pst_length);
return OEMCrypto_SUCCESS;
}
@@ -1426,7 +1437,7 @@ OEMCryptoResult OPKI_ShrinkUsageTableHeader(uint32_t new_entry_count,
LOGE("Usage table not initialized");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
- if (new_entry_count >= g_usage_table.table_size) {
+ if (new_entry_count > g_usage_table.table_size) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
for (size_t i = new_entry_count; i < g_usage_table.table_size; i++) {
diff --git a/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.h b/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.h
index 0aa40b2..ba8ec21 100644
--- a/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.h
+++ b/oemcrypto/opk/oemcrypto_ta/oemcrypto_usage_table.h
@@ -170,9 +170,9 @@ NO_IGNORE_RESULT OEMCryptoResult OPKI_SignReleaseRequest(
* or deactivating the license. Pointers must be non-null and are owned by the
* caller. */
NO_IGNORE_RESULT OEMCryptoResult OPKI_GetUsageEntryInfo(
- OEMCrypto_SESSION session_id, OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_SESSION session_id, OEMCrypto_UsageEntryStatus* status,
int64_t* seconds_since_license_received,
- int64_t* seconds_since_first_decrypt);
+ int64_t* seconds_since_first_decrypt, uint8_t* pst, size_t* pst_length);
/**
* Move the usage entry associated with |session| to the new index in the
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi/README.md b/oemcrypto/opk/oemcrypto_ta/wtpi/README.md
index 066082d..8f07d7e 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi/README.md
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi/README.md
@@ -3,36 +3,33 @@
Some of the headers in wtpi/ directory are tested by the code in wtpi_test/.
wtpi_test uses serialization/generator/scrape_interface.py to parse the WTPI
interface declarations and generate serialization APIs such as:
-* OPK_Pack_SaveGenerationNumber_Request(),
-* OPK_Unpack_K1_DeriveKeyFromKeyHandle_Response(),
+
+* `OPK_Pack_SaveGenerationNumber_Request()`
+* `OPK_Unpack_K1_DeriveKeyFromKeyHandle_Response()`
* ...
In order for the types of the parameters of these WTPI interfaces to be
correctly determined and inserted into the auto-generated
-OPK_Pack_* / OPK_Unpack_* functions, certain naming conventions have to be
-followed:
-
-* To pack a variable length buffer X with type uint8_t*, the size of the
-array must be named as "X_length" or XLength".
-* If an output variable length buffer doesn't have an output size specified in
-the parameter list, and is supposed to have the same size as the input buffer,
-then the output buffer must be named as "out_buffer".
-
-Below is an example following the naming convention above:
-```
-OEMCryptoResult WTPI_C1_SHA256(const uint8_t* input, size_t input_length,
- uint8_t* out_buffer);
-```
-You can find more details in scrape_interface.py for what is looked for by the
-parser.
+OPK_Pack_* / OPK_Unpack_* functions,
+[certain naming conventions][naming-conventions] have to be followed.
WTPI interfaces that are currently covered by wtpi_test:
-* wtpi_generation_number_interface.h,
-* wtpi_crypto_and_key_management_interface_layer1.h,
-* wtpi_crypto_asymmetric_interface.h,
-* wtpi_crc32_interface.h,
-* wtpi_provisioning_4_interface.h,
+
+* wtpi_generation_number_interface.h
+* wtpi_crypto_and_key_management_interface_layer1.h
+* wtpi_crypto_asymmetric_interface.h
+* wtpi_provisioning_4_interface.h
+* wtpi_crc32_interface.h
+* wtpi_clock_interface_layer1.h
+* wtpi_config_interface.h
+* wtpi_device_key_interface.h
+
+However, all WTPI interface may potentially be covered someday, so it's best
+practice to always follow [the naming conventions][naming-conventions].
Please be cautious when updating parameter names in these interfaces. It can
potentially break the auto-generated serialization functions used by the WTPI
-tests if the naming convention is not enforced.
+tests if the naming conventions are not enforced. It can also cause the
+generator to generate invalid or insecure code.
+
+[naming-conventions]: https://g3doc.corp.google.com/video/widevine/g3doc/devices/oec_function_conventions.md
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_clock_interface_layer1.h b/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_clock_interface_layer1.h
index 6e7aa88..2cc47e0 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_clock_interface_layer1.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_clock_interface_layer1.h
@@ -65,7 +65,7 @@ OEMCryptoResult WTPI_TerminateClock(void);
* https://developers.google.com/widevine/drm/client/oemcrypto/v16/odk-timers
* for the definition of insecure clock, secure timer, and secure clock.
*/
-OEMCrypto_Clock_Security_Level WTPI_GetClockType(void);
+OEMCrypto_ClockSecurityLevel WTPI_GetClockType(void);
/// @}
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_crypto_asymmetric_interface.h b/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_crypto_asymmetric_interface.h
index 8670711..f448c0d 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_crypto_asymmetric_interface.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_crypto_asymmetric_interface.h
@@ -332,9 +332,9 @@ OEMCryptoResult WTPI_GetSignatureHashAlgorithm(
* key pair is placed into |private_key_handle| and |public_key|.
*
* @param[in] deriving_key: The deriving key in clear bytes.
- * @param[in] deriving_key_length: size of of |deriving_key| in bytes.
+ * @param[in] deriving_key_length: size of |deriving_key| in bytes.
* @param[in] context: input context for deriving key.
- * @param[in] context_length: size of of |context| in bytes.
+ * @param[in] context_length: size of |context| in bytes.
* @param[in] key_type: type of asymmetric key.
* @param[out] private_key_handle: The derived private key.
* @param[out] public_key: The derived public key.
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_reference/cose_util.c b/oemcrypto/opk/oemcrypto_ta/wtpi_reference/cose_util.c
index 7de7870..58de948 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_reference/cose_util.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_reference/cose_util.c
@@ -13,6 +13,7 @@
#include "dice/cbor_writer.h"
#include "dice/config.h"
#include "dice/dice.h"
+#include "oemcrypto_api_macros.h"
#include "oemcrypto_check_macros.h"
#include "wtpi_crypto_and_key_management_interface_layer1.h"
#include "wtpi_crypto_asymmetric_interface.h"
@@ -217,20 +218,23 @@ static DiceResult EncodeConfigurationDescriptor(size_t buffer_size,
CborOutInit(buffer, buffer_size, &out);
CborWriteMap(/*num_pairs=*/2, &out);
+ char str_buf[32] = {0};
// Add component name.
CborWriteInt(kComponentNameLabel, &out);
if (is_leaf) {
// The leaf certificate's component name must contain "Widevine".
CborWriteTstr("Widevine", &out);
} else {
- char buf[32] = {0};
- snprintf(buf, sizeof(buf), "Component %u", entry_index);
- CborWriteTstr(buf, &out);
+ snprintf(str_buf, sizeof(str_buf), "Component %u", entry_index);
+ CborWriteTstr(str_buf, &out);
+ memset(str_buf, 0, sizeof(str_buf));
}
// Add component version.
CborWriteInt(kComponentVersionLabel, &out);
- CborWriteTstr("19", &out);
+ snprintf(str_buf, sizeof(str_buf), "%d", API_MAJOR_VERSION);
+ CborWriteTstr(str_buf, &out);
+ memset(str_buf, 0, sizeof(str_buf));
if (CborOutOverflowed(&out)) {
return kDiceResultBufferTooSmall;
@@ -423,7 +427,13 @@ static OEMCryptoResult GenerateEncodedBccPayload(
// Add the profile name.
CborWriteInt(kProfileNameLabel, &cbor_out);
- CborWriteTstr("android.15", &cbor_out);
+ if (is_leaf) {
+ snprintf(str_buf, sizeof(str_buf), "widevine.%d", API_MAJOR_VERSION);
+ CborWriteTstr(str_buf, &cbor_out);
+ memset(str_buf, 0, sizeof(str_buf));
+ } else {
+ CborWriteTstr("android.15", &cbor_out);
+ }
// Add the subject public key.
CborWriteInt(kSubjectPublicKeyLabel, &cbor_out);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_clock_and_gn_layer1.c b/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_clock_and_gn_layer1.c
index 15cdcdf..28bbed6 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_clock_and_gn_layer1.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_clock_and_gn_layer1.c
@@ -208,7 +208,9 @@ OEMCryptoResult WTPI_TerminateClock(void) {
return GetTrustedTimeAndSave(&temp, true);
}
-OEMCrypto_Clock_Security_Level WTPI_GetClockType(void) { return kSecureTimer; }
+OEMCrypto_ClockSecurityLevel WTPI_GetClockType(void) {
+ return OEMCrypto_InsecureClock;
+}
OEMCryptoResult WTPI_GetTrustedTime(uint64_t* time_in_s) {
RETURN_INVALID_CONTEXT_IF_NULL(time_in_s);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_ref_compat.c b/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_ref_compat.c
index 96ab820..1c13927 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_ref_compat.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_reference/wtpi_ref_compat.c
@@ -26,7 +26,7 @@ typedef struct {
int64_t time_of_license_received;
int64_t time_of_first_decrypt;
int64_t time_of_last_decrypt;
- enum OEMCrypto_Usage_Entry_Status status;
+ enum OEMCrypto_UsageEntryStatus status;
uint8_t mac_key_server[MAC_KEY_SIZE];
uint8_t mac_key_client[MAC_KEY_SIZE];
uint32_t index;
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/README.md b/oemcrypto/opk/oemcrypto_ta/wtpi_test/README.md
index 3819e12..026f539 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/README.md
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/README.md
@@ -29,7 +29,7 @@ To add more WTPI tests for a new WTPI interface
- Add WTPI header file name to
oemcrypto/opk/serialization/generator/api_generator.cpp and
oemcrypto/opk/serialization/generator/dispatcher_generator.cpp
-- Run jenkins/opk_tee_interface_tests as a quick check. It generates all of the
+- Run jenkins/opk_tee_interface_test as a quick check. It generates all of the
required serialization files before running the test, and will throw an error
if there is a problem with the above steps.
- Write test cases. If needed, create a new .cpp file and add it to the
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.c
index 5ad9f67..96d27fb 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.c
@@ -121,13 +121,13 @@ bool Is_Valid_OEMCryptoResult(uint32_t value) {
}
}
-bool Is_Valid_OEMCrypto_Usage_Entry_Status(uint32_t value) {
+bool Is_Valid_OEMCrypto_UsageEntryStatus(uint32_t value) {
switch (value) {
- case 0: /* kUnused */
- case 1: /* kActive */
- case 2: /* kInactive */
- case 3: /* kInactiveUsed */
- case 4: /* kInactiveUnused */
+ case 0: /* OEMCrypto_Unused */
+ case 1: /* OEMCrypto_Active */
+ case 2: /* OEMCrypto_Inactive */
+ case 3: /* OEMCrypto_InactiveUsed */
+ case 4: /* OEMCrypto_InactiveUnused */
return true;
default:
return false;
@@ -156,8 +156,8 @@ bool Is_Valid_OEMCrypto_LicenseType(uint32_t value) {
bool Is_Valid_OEMCrypto_PrivateKeyType(uint32_t value) {
switch (value) {
- case 0: /* OEMCrypto_RSA_Private_Key */
- case 1: /* OEMCrypto_ECC_Private_Key */
+ case 0: /* OEMCrypto_RSAPrivateKey */
+ case 1: /* OEMCrypto_ECCPrivateKey */
return true;
default:
return false;
@@ -166,9 +166,33 @@ bool Is_Valid_OEMCrypto_PrivateKeyType(uint32_t value) {
bool Is_Valid_OEMCrypto_TimerDelayBase(uint32_t value) {
switch (value) {
- case 0: /* OEMCrypto_License_Start */
- case 1: /* OEMCrypto_License_Load */
- case 2: /* OEMCrypto_First_Decrypt */
+ case 0: /* OEMCrypto_LicenseStart */
+ case 1: /* OEMCrypto_LicenseLoad */
+ case 2: /* OEMCrypto_FirstDecrypt */
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Is_Valid_OEMCrypto_ClockSecurityLevel(uint32_t value) {
+ switch (value) {
+ case 0: /* OEMCrypto_InsecureClock */
+ case 1: /* OEMCrypto_MonotonicClock */
+ case 2: /* OEMCrypto_SecureClock */
+ case 3: /* OEMCrypto_HardwareSecureClock */
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Is_Valid_OEMCrypto_DeCENC_Mitigation_Option(uint32_t value) {
+ switch (value) {
+ case 0: /* OEMCrypto_DeCENC_Mitigation_Option_None */
+ case 1: /* OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream */
+ case 2: /* OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream */
+ case 4: /* OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding */
return true;
default:
return false;
@@ -249,6 +273,29 @@ void OPK_Pack_OEMCrypto_KeyObject(ODK_Message* msg,
(const OEMCrypto_Substring*)&obj->key_control);
}
+void OPK_Pack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo const* obj) {
+ OPK_Pack_OEMCrypto_Substring(
+ msg, (const OEMCrypto_Substring*)&obj->authentication_key);
+ OPK_Pack_OEMCrypto_Substring(
+ msg, (const OEMCrypto_Substring*)&obj->authentication_key_iv);
+}
+
+void OPK_Pack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2 const* obj) {
+ OPK_Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_id);
+ OPK_Pack_OEMCrypto_Substring(msg,
+ (const OEMCrypto_Substring*)&obj->key_data_iv);
+ OPK_Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_data);
+ OPK_Pack_OEMCrypto_Substring(
+ msg, (const OEMCrypto_Substring*)&obj->key_control_iv);
+ OPK_Pack_OEMCrypto_Substring(msg,
+ (const OEMCrypto_Substring*)&obj->key_control);
+ OPK_Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ msg,
+ (const OEMCrypto_DeCENC_Mitigation_Info*)&obj->decenc_mitigation_info);
+}
+
void OPK_Unpack_OEMCrypto_Substring(ODK_Message* msg,
OEMCrypto_Substring* obj) {
OEMCrypto_Substring tmp_obj;
@@ -320,6 +367,31 @@ void OPK_Unpack_OEMCrypto_KeyObject(ODK_Message* msg,
OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_control);
}
+void OPK_Unpack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo* obj) {
+ OEMCrypto_AuthenticationKeyInfo tmp_obj;
+ if (obj == NULL) {
+ obj = &tmp_obj;
+ }
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->authentication_key);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->authentication_key_iv);
+}
+
+void OPK_Unpack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2* obj) {
+ OEMCrypto_KeyObjectV2 tmp_obj;
+ if (obj == NULL) {
+ obj = &tmp_obj;
+ }
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_id);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_data);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_control_iv);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_control);
+ OPK_Unpack_OEMCrypto_DeCENC_Mitigation_Info(msg,
+ &obj->decenc_mitigation_info);
+}
+
void OPK_PackNullable_uint64_t(ODK_Message* msg, const uint64_t* value) {
OPK_PackBoolValue(msg, value == NULL);
if (value) {
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.h b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.h
index 4369d57..20d60c0 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/GEN_common_serializer.h
@@ -24,11 +24,13 @@ extern "C" {
bool SuccessResult(OEMCryptoResult result);
bool Is_Valid_OEMCryptoResult(uint32_t value);
-bool Is_Valid_OEMCrypto_Usage_Entry_Status(uint32_t value);
+bool Is_Valid_OEMCrypto_UsageEntryStatus(uint32_t value);
bool Is_Valid_OEMCrypto_ProvisioningRenewalType(uint32_t value);
bool Is_Valid_OEMCrypto_LicenseType(uint32_t value);
bool Is_Valid_OEMCrypto_PrivateKeyType(uint32_t value);
bool Is_Valid_OEMCrypto_TimerDelayBase(uint32_t value);
+bool Is_Valid_OEMCrypto_ClockSecurityLevel(uint32_t value);
+bool Is_Valid_OEMCrypto_DeCENC_Mitigation_Option(uint32_t value);
bool Is_Valid_OPK_OutputBuffer_Type(uint32_t value);
bool Is_Valid_OPK_FeatureStatus(uint32_t value);
void OPK_Pack_OEMCrypto_Substring(ODK_Message* msg,
@@ -43,6 +45,10 @@ void OPK_Pack_OEMCrypto_DTCP2_CMI_Packet(ODK_Message* msg,
OEMCrypto_DTCP2_CMI_Packet const* obj);
void OPK_Pack_OEMCrypto_KeyObject(ODK_Message* msg,
OEMCrypto_KeyObject const* obj);
+void OPK_Pack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo const* obj);
+void OPK_Pack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2 const* obj);
void OPK_Unpack_OEMCrypto_Substring(ODK_Message* msg, OEMCrypto_Substring* obj);
void OPK_Unpack_OEMCrypto_DTCP2_CMI_Descriptor_0(
ODK_Message* msg, OEMCrypto_DTCP2_CMI_Descriptor_0* obj);
@@ -53,6 +59,10 @@ void OPK_Unpack_OEMCrypto_DTCP2_CMI_Descriptor_2(
void OPK_Unpack_OEMCrypto_DTCP2_CMI_Packet(ODK_Message* msg,
OEMCrypto_DTCP2_CMI_Packet* obj);
void OPK_Unpack_OEMCrypto_KeyObject(ODK_Message* msg, OEMCrypto_KeyObject* obj);
+void OPK_Unpack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo* obj);
+void OPK_Unpack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2* obj);
void OPK_PackNullable_uint64_t(ODK_Message* msg, const uint64_t* value);
void OPK_UnpackNullable_uint64_t(ODK_Message* msg, uint64_t** value);
void OPK_UnpackAlloc_uint64_t(ODK_Message* msg, uint64_t** value);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.c
index cd8c52a..ab8ffcb 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.c
@@ -5,6 +5,7 @@
*/
#include "common_special_cases.h"
+#include "GEN_common_serializer.h"
#include "log_macros.h"
#include "odk_attributes.h"
#include "opk_serialization_base.h"
@@ -167,8 +168,8 @@ void OPK_Unpack_OEMCrypto_SharedMemory(ODK_Message* message,
ODK_MESSAGE_SETSTATUS(message, MESSAGE_STATUS_NULL_POINTER_ERROR);
}
-void OPK_Pack_OEMCrypto_Clock_Security_Level(
- ODK_Message* message, const OEMCrypto_Clock_Security_Level* value) {
+void OPK_Pack_OEMCrypto_ClockSecurityLevel(
+ ODK_Message* message, const OEMCrypto_ClockSecurityLevel* value) {
if (value == NULL) {
ODK_MESSAGE_SETSTATUS(message, MESSAGE_STATUS_NULL_POINTER_ERROR);
return;
@@ -177,8 +178,8 @@ void OPK_Pack_OEMCrypto_Clock_Security_Level(
OPK_Pack_uint32_t(message, (const uint32_t*)value);
}
-void OPK_Unpack_OEMCrypto_Clock_Security_Level(
- ODK_Message* message, OEMCrypto_Clock_Security_Level* value) {
+void OPK_Unpack_OEMCrypto_ClockSecurityLevel(
+ ODK_Message* message, OEMCrypto_ClockSecurityLevel* value) {
OPK_Unpack_uint32_t(message, (uint32_t*)value);
}
@@ -242,8 +243,8 @@ void OPK_Pack_OEMCrypto_HDCP_Capability(
OPK_Pack_uint32_t(message, (const uint32_t*)value);
}
-void OPK_Pack_OEMCrypto_Usage_Entry_Status(
- ODK_Message* message, const OEMCrypto_Usage_Entry_Status* status) {
+void OPK_Pack_OEMCrypto_UsageEntryStatus(
+ ODK_Message* message, const OEMCrypto_UsageEntryStatus* status) {
if (status == NULL) {
ODK_MESSAGE_SETSTATUS(message, MESSAGE_STATUS_NULL_POINTER_ERROR);
return;
@@ -282,8 +283,8 @@ void OPK_Unpack_OEMCrypto_HDCP_Capability(ODK_Message* message,
OPK_Unpack_uint32_t(message, (uint32_t*)value);
}
-void OPK_Unpack_OEMCrypto_Usage_Entry_Status(
- ODK_Message* message, OEMCrypto_Usage_Entry_Status* status) {
+void OPK_Unpack_OEMCrypto_UsageEntryStatus(ODK_Message* message,
+ OEMCrypto_UsageEntryStatus* status) {
OPK_Unpack_uint32_t(message, (uint32_t*)status);
}
@@ -316,3 +317,42 @@ void OPK_Unpack_CertSignatureType(ODK_Message* message,
CertSignatureType* value) {
OPK_Unpack_uint32_t(message, (uint32_t*)value);
}
+
+void OPK_Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info const* obj) {
+ OPK_Pack_uint32_t(
+ msg, (const OEMCrypto_DeCENC_Mitigation_Option*)&obj->mitigation_option);
+ switch (obj->mitigation_option) {
+ case OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream:
+ OPK_Pack_OEMCrypto_AuthenticationKeyInfo(
+ msg, &obj->configuration_options.authentication_key_info);
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream:
+ // No configuration options
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding:
+ // No configuration options
+ break;
+ default:
+ break;
+ }
+}
+
+void OPK_Unpack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info* obj) {
+ OPK_Unpack_uint32_t(msg, &obj->mitigation_option);
+ switch (obj->mitigation_option) {
+ case OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream:
+ OPK_Unpack_OEMCrypto_AuthenticationKeyInfo(
+ msg, &obj->configuration_options.authentication_key_info);
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream:
+ // No configuration options
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding:
+ // No configuration options
+ break;
+ default:
+ break;
+ }
+}
\ No newline at end of file
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.h b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.h
index 99fa1eb..0956e3c 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/common/common_special_cases.h
@@ -50,10 +50,10 @@ void OPK_Pack_OEMCrypto_SharedMemory(ODK_Message* message,
void OPK_Unpack_OEMCrypto_SharedMemory(ODK_Message* message,
OEMCrypto_SharedMemory* value);
-void OPK_Pack_OEMCrypto_Clock_Security_Level(
- ODK_Message* msg, const OEMCrypto_Clock_Security_Level* value);
-void OPK_Unpack_OEMCrypto_Clock_Security_Level(
- ODK_Message* msg, OEMCrypto_Clock_Security_Level* value);
+void OPK_Pack_OEMCrypto_ClockSecurityLevel(
+ ODK_Message* msg, const OEMCrypto_ClockSecurityLevel* value);
+void OPK_Unpack_OEMCrypto_ClockSecurityLevel(
+ ODK_Message* msg, OEMCrypto_ClockSecurityLevel* value);
void OPK_Pack_OEMCrypto_Security_Level(ODK_Message* msg,
const OEMCrypto_Security_Level* value);
@@ -67,8 +67,8 @@ void OPK_Pack_OEMCrypto_WatermarkingSupport(
ODK_Message* msg, const OEMCrypto_WatermarkingSupport* value);
void OPK_Pack_OEMCrypto_HDCP_Capability(ODK_Message* msg,
const OEMCrypto_HDCP_Capability* value);
-void OPK_Pack_OEMCrypto_Usage_Entry_Status(
- ODK_Message* msg, const OEMCrypto_Usage_Entry_Status* status);
+void OPK_Pack_OEMCrypto_UsageEntryStatus(
+ ODK_Message* msg, const OEMCrypto_UsageEntryStatus* status);
void OPK_Unpack_OEMCrypto_Security_Level(ODK_Message* msg,
OEMCrypto_Security_Level* value);
void OPK_Unpack_OEMCrypto_ProvisioningMethod(
@@ -84,10 +84,13 @@ void OPK_Pack_OEMCrypto_SignatureHashAlgorithm(
ODK_Message* message, const OEMCrypto_SignatureHashAlgorithm* value);
void OPK_Unpack_OEMCrypto_SignatureHashAlgorithm(
ODK_Message* message, OEMCrypto_SignatureHashAlgorithm* value);
-void OPK_Unpack_OEMCrypto_Usage_Entry_Status(
- ODK_Message* message, OEMCrypto_Usage_Entry_Status* status);
+void OPK_Unpack_OEMCrypto_UsageEntryStatus(ODK_Message* message,
+ OEMCrypto_UsageEntryStatus* status);
void OPK_Pack_CertSignatureType(ODK_Message* message, CertSignatureType* value);
void OPK_Unpack_CertSignatureType(ODK_Message* message,
CertSignatureType* value);
-
+void OPK_Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info const* obj);
+void OPK_Unpack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info* obj);
#endif
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/crypto_test.cpp b/oemcrypto/opk/oemcrypto_ta/wtpi_test/crypto_test.cpp
index 7903616..e49e763 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/crypto_test.cpp
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/crypto_test.cpp
@@ -1780,11 +1780,12 @@ TEST_F(CryptoTest, ECCLoadKeyAndSign) {
TEST_F(CryptoTest, GetBCCTypeProv4AndOthers) {
OEMCrypto_ProvisioningMethod method = WTPI_GetProvisioningMethod();
- OEMCrypto_BCCType bcc_type;
+ OEMCrypto_BCCType bcc_type = static_cast(-1);
OEMCryptoResult res = WTPI_GetBCCType(&bcc_type);
if (method == OEMCrypto_BootCertificateChain) {
ASSERT_EQ(res, OEMCrypto_SUCCESS);
+ ASSERT_NE(bcc_type, static_cast(-1));
} else {
ASSERT_EQ(res, OEMCrypto_ERROR_NOT_IMPLEMENTED);
}
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_oemcrypto_tee_test_api.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_oemcrypto_tee_test_api.c
index 3192394..3118ddd 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_oemcrypto_tee_test_api.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_oemcrypto_tee_test_api.c
@@ -2065,9 +2065,9 @@ cleanup_and_return:
return result;
}
-OEMCrypto_Clock_Security_Level WTPI_GetClockType(void) {
+OEMCrypto_ClockSecurityLevel WTPI_GetClockType(void) {
pthread_mutex_lock(&api_lock);
- OEMCrypto_Clock_Security_Level result = kInsecureClock;
+ OEMCrypto_ClockSecurityLevel result = OEMCrypto_InsecureClock;
ODK_Message request = ODK_Message_Create(NULL, 0);
ODK_Message response = ODK_Message_Create(NULL, 0);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.c
index 7fb1e8c..77208ea 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.c
@@ -2128,12 +2128,15 @@ ODK_Message OPK_Pack_GetClockType_Request(void) {
}
void OPK_Unpack_GetClockType_Response(ODK_Message* msg,
- OEMCrypto_Clock_Security_Level* result) {
+ OEMCrypto_ClockSecurityLevel* result) {
uint32_t api_value = UINT32_MAX;
OPK_Unpack_uint32_t(msg, &api_value);
if (api_value != 10057)
ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
- OPK_Unpack_OEMCrypto_Clock_Security_Level(msg, result);
+ OPK_Unpack_uint32_t(msg, result);
+ if (!Is_Valid_OEMCrypto_ClockSecurityLevel(*result)) {
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ }
OPK_UnpackEOM(msg);
OPK_SharedBuffer_FinalizeUnpacking();
}
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.h b/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.h
index a9bb7fc..4930619 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/ree/GEN_ree_serializer.h
@@ -327,7 +327,7 @@ void OPK_Unpack_TerminateClock_Response(ODK_Message* msg,
OEMCryptoResult* result);
ODK_Message OPK_Pack_GetClockType_Request(void);
void OPK_Unpack_GetClockType_Response(ODK_Message* msg,
- OEMCrypto_Clock_Security_Level* result);
+ OEMCrypto_ClockSecurityLevel* result);
ODK_Message OPK_Pack_GetSecurityLevel_Request(void);
void OPK_Unpack_GetSecurityLevel_Response(ODK_Message* msg,
OEMCrypto_Security_Level* result);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_dispatcher.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_dispatcher.c
index 25cca8d..c0c7540 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_dispatcher.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_dispatcher.c
@@ -84,6 +84,23 @@ void OPK_Init_OEMCrypto_KeyObject(OEMCrypto_KeyObject* obj) {
OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_control);
}
+void OPK_Init_OEMCrypto_AuthenticationKeyInfo(
+ OEMCrypto_AuthenticationKeyInfo* obj) {
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->authentication_key);
+ OPK_Init_OEMCrypto_Substring(
+ (OEMCrypto_Substring*)&obj->authentication_key_iv);
+}
+
+void OPK_Init_OEMCrypto_KeyObjectV2(OEMCrypto_KeyObjectV2* obj) {
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_id);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_data_iv);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_data);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_control_iv);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_control);
+ OPK_Init_OEMCrypto_DeCENC_Mitigation_Info(
+ (OEMCrypto_DeCENC_Mitigation_Info*)&obj->decenc_mitigation_info);
+}
+
/* See opk_dispatcher.h for definition of OPK_DispatchMessage() */
ODK_MessageStatus OPK_DispatchMessage(ODK_Message* request,
ODK_Message* response) {
@@ -1240,9 +1257,8 @@ ODK_MessageStatus OPK_DispatchMessage(ODK_Message* request,
{
OPK_Unpack_GetClockType_Request(request);
if (!ODK_Message_IsValid(request)) goto handle_invalid_request;
- OEMCrypto_Clock_Security_Level result;
- OPK_Init_OEMCrypto_Clock_Security_Level(
- (OEMCrypto_Clock_Security_Level*)&result);
+ OEMCrypto_ClockSecurityLevel result;
+ OPK_Init_uint32_t((uint32_t*)&result);
LOGD("GetClockType");
result = WTPI_GetClockType();
*response = OPK_Pack_GetClockType_Response(result);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.c
index 1dfdd04..4a1ab8b 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.c
@@ -1647,11 +1647,11 @@ void OPK_Unpack_GetClockType_Request(ODK_Message* msg) {
}
ODK_Message OPK_Pack_GetClockType_Response(
- OEMCrypto_Clock_Security_Level result) {
+ OEMCrypto_ClockSecurityLevel result) {
uint32_t api_value = 10057; /* from _tee10057 */
ODK_Message msg = TOS_Transport_GetResponse();
OPK_Pack_uint32_t(&msg, &api_value);
- OPK_Pack_OEMCrypto_Clock_Security_Level(&msg, &result);
+ OPK_Pack_uint32_t(&msg, &result);
OPK_PackEOM(&msg);
OPK_SharedBuffer_FinalizePacking();
return msg;
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.h b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.h
index f24fe23..f616a66 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/GEN_tee_serializer.h
@@ -297,8 +297,7 @@ ODK_Message OPK_Pack_InitializeClock_Response(OEMCryptoResult result);
void OPK_Unpack_TerminateClock_Request(ODK_Message* msg);
ODK_Message OPK_Pack_TerminateClock_Response(OEMCryptoResult result);
void OPK_Unpack_GetClockType_Request(ODK_Message* msg);
-ODK_Message OPK_Pack_GetClockType_Response(
- OEMCrypto_Clock_Security_Level result);
+ODK_Message OPK_Pack_GetClockType_Response(OEMCrypto_ClockSecurityLevel result);
void OPK_Unpack_GetSecurityLevel_Request(ODK_Message* msg);
ODK_Message OPK_Pack_GetSecurityLevel_Response(OEMCrypto_Security_Level result);
void OPK_Unpack_GetProvisioningMethod_Request(ODK_Message* msg);
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.c b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.c
index 71fe99e..ab73051 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.c
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.c
@@ -69,10 +69,9 @@ void OPK_Init_KeySize(KeySize* obj) {
}
}
-void OPK_Init_OEMCrypto_Clock_Security_Level(
- OEMCrypto_Clock_Security_Level* obj) {
+void OPK_Init_OEMCrypto_ClockSecurityLevel(OEMCrypto_ClockSecurityLevel* obj) {
if (obj) {
- memset(obj, 0, sizeof(OEMCrypto_Clock_Security_Level));
+ memset(obj, 0, sizeof(OEMCrypto_ClockSecurityLevel));
}
}
diff --git a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.h b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.h
index 23435de..38a9d67 100644
--- a/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.h
+++ b/oemcrypto/opk/oemcrypto_ta/wtpi_test/tee/tee_special_cases.h
@@ -19,8 +19,7 @@ void OPK_Init_AsymmetricKeyType(AsymmetricKeyType* obj);
void OPK_Init_WTPI_AsymmetricKey_Handle(WTPI_AsymmetricKey_Handle* obj);
void OPK_Init_RSA_Padding_Scheme(RSA_Padding_Scheme* obj);
void OPK_Init_KeySize(KeySize* obj);
-void OPK_Init_OEMCrypto_Clock_Security_Level(
- OEMCrypto_Clock_Security_Level* obj);
+void OPK_Init_OEMCrypto_ClockSecurityLevel(OEMCrypto_ClockSecurityLevel* obj);
void OPK_Init_OEMCrypto_Security_Level(OEMCrypto_Security_Level* obj);
void OPK_Init_OEMCrypto_ProvisioningMethod(OEMCrypto_ProvisioningMethod* obj);
void OPK_Init_OEMCrypto_WatermarkingSupport(OEMCrypto_WatermarkingSupport* obj);
diff --git a/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/Makefile b/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/Makefile
index 1931349..af2bb09 100644
--- a/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/Makefile
+++ b/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/Makefile
@@ -55,7 +55,16 @@ cflags += \
-DWTPI_BUILD_INFO=\"$(WTPI_BUILD_INFO)\" \
-DSUPPORT_CAS \
-DWV_POSIX_RESOURCE_ID=\"$(project)\" \
- -D_DEFAULT_SOURCE
+ -DOPK_CONFIG_SOC_VENDOR_NAME=$(SOC_VENDOR) \
+ -DOPK_CONFIG_SOC_MODEL_NAME=$(SOC_MODEL) \
+ -DOPK_CONFIG_TEE_OS_NAME=$(TEE_OS) \
+ -DOPK_CONFIG_TEE_OS_VERSION=$(TEE_VERSION) \
+ -DOPK_CONFIG_DEVICE_FORM_FACTOR=$(DEVICE_FORM_FACTOR) \
+ -DOPK_CONFIG_IMPLEMENTER_NAME=$(IMPLEMENTER) \
+ -DOPK_CONFIG_PROVISIONING_METHOD=$(PROVISIONING_METHOD) \
+ -D_DEFAULT_SOURCE \
+ -fstack-protector-strong \
+ -D_DEBUG
ldflags = \
-lrt -lpthread \
diff --git a/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/data_share.h b/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/data_share.h
index 8b623e0..095930a 100644
--- a/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/data_share.h
+++ b/oemcrypto/opk/ports/linux/cas/tee/tee_simulator_cas/data_share.h
@@ -9,7 +9,7 @@
#include
#include
#include "OEMCryptoCENC.h"
-#include "wtpi_config_macros.h"
+#include "opk_config.h"
#include "wtpi_crypto_and_key_management_interface_layer1.h"
#ifdef __cplusplus
diff --git a/oemcrypto/opk/ports/linux/common/posix_services.h b/oemcrypto/opk/ports/linux/common/posix_services.h
index 67242b2..5bdc54c 100644
--- a/oemcrypto/opk/ports/linux/common/posix_services.h
+++ b/oemcrypto/opk/ports/linux/common/posix_services.h
@@ -48,6 +48,9 @@ class Semaphore : public Resource {
}
}
+ Semaphore(const Semaphore&) = delete;
+ void operator=(const Semaphore&) = delete;
+
~Semaphore() {
if (sem_) {
sem_close(sem_);
@@ -63,9 +66,6 @@ class Semaphore : public Resource {
private:
sem_t* sem_;
-
- Semaphore(const Semaphore&) = delete;
- void operator=(const Semaphore&) = delete;
};
// Manage blocks of shared memory across process boundaries using
@@ -83,6 +83,9 @@ class SharedMemory : public Resource {
Open();
}
+ SharedMemory(const SharedMemory&) = delete;
+ void operator=(const SharedMemory&) = delete;
+
~SharedMemory() { Close(); }
uint8_t* GetAddress() const { return address_; }
@@ -127,10 +130,8 @@ class SharedMemory : public Resource {
fd_ = -1;
}
}
-
- SharedMemory(const SharedMemory&) = delete;
- void operator=(const SharedMemory&) = delete;
};
-}; // namespace posix
+
+} // namespace posix
#endif /* LINUX_IPC_POSIX_SERVICES_H_ */
diff --git a/oemcrypto/opk/ports/linux/host/oemcrypto_unittests/oemcrypto_ref_compat_test.cpp b/oemcrypto/opk/ports/linux/host/oemcrypto_unittests/oemcrypto_ref_compat_test.cpp
index d28a2c4..8123b66 100644
--- a/oemcrypto/opk/ports/linux/host/oemcrypto_unittests/oemcrypto_ref_compat_test.cpp
+++ b/oemcrypto/opk/ports/linux/host/oemcrypto_unittests/oemcrypto_ref_compat_test.cpp
@@ -19,7 +19,7 @@ TEST_F(OEMCryptoProv2ReferenceWrap, LoadWrappedKey) {
OEMCryptoResult sts = OEMCrypto_ERROR_INVALID_CONTEXT;
sts = OEMCrypto_LoadDRMPrivateKey(
- session_.session_id(), OEMCrypto_RSA_Private_Key, wrapped_rsa_key.data(),
+ session_.session_id(), OEMCrypto_RSAPrivateKey, wrapped_rsa_key.data(),
wrapped_rsa_key.size());
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
diff --git a/oemcrypto/opk/ports/linux/oemcrypto_tee_simulator.gyp b/oemcrypto/opk/ports/linux/oemcrypto_tee_simulator.gyp
index 3108e1a..ad29bfc 100644
--- a/oemcrypto/opk/ports/linux/oemcrypto_tee_simulator.gyp
+++ b/oemcrypto/opk/ports/linux/oemcrypto_tee_simulator.gyp
@@ -36,9 +36,9 @@
'<(serialization_adapter_dir)/tos_shared_memory.cpp',
'<(serialization_adapter_dir)/tos_transport.cpp',
'<(util_dir)/src/platform.cpp',
- '<(util_dir)/src/rw_lock.cpp',
'<(util_dir)/src/string_conversions.cpp',
'<(util_dir)/src/string_format.cpp',
+ '<(util_dir)/src/wv_duration.cpp',
],
'dependencies': [
'<(serialization_dir)/tee/tee.gyp:opk_tee',
@@ -60,9 +60,9 @@
'<(serialization_adapter_dir)/tos_shared_memory.cpp',
'<(serialization_adapter_dir)/tos_transport.cpp',
'<(util_dir)/src/platform.cpp',
- '<(util_dir)/src/rw_lock.cpp',
'<(util_dir)/src/string_conversions.cpp',
'<(util_dir)/src/string_format.cpp',
+ '<(util_dir)/src/wv_duration.cpp',
],
'dependencies': [
'<(serialization_dir)/tee/tee.gyp:opk_tee',
diff --git a/oemcrypto/opk/ports/linux/ta/common/clock.cpp b/oemcrypto/opk/ports/linux/ta/common/clock.cpp
index 1eda0cb..67668d0 100644
--- a/oemcrypto/opk/ports/linux/ta/common/clock.cpp
+++ b/oemcrypto/opk/ports/linux/ta/common/clock.cpp
@@ -3,18 +3,36 @@
// Agreement.
//
// Clock - implemented using the standard linux time library
-
#include "clock.h"
+#include
+
#include
-namespace wvutil {
+#include "wv_timestamp.h"
+namespace wvutil {
int64_t Clock::GetCurrentTime() {
- struct timeval tv;
- tv.tv_sec = tv.tv_usec = 0;
- gettimeofday(&tv, nullptr);
+ struct timeval tv = {};
+ if (gettimeofday(&tv, nullptr) != 0) {
+ // This might be called within logging functions, do not
+ // log error.
+ return 0;
+ }
return tv.tv_sec;
}
+Timestamp Clock::GetCurrentTimestamp() {
+ struct timeval tv = {};
+ if (gettimeofday(&tv, nullptr) != 0) {
+ // This might be called within logging functions, do not
+ // log error.
+ return Timestamp();
+ }
+ constexpr int kMaxUSec = 999999;
+ if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec > kMaxUSec)
+ return Timestamp();
+ return Timestamp::FromUnixSeconds(static_cast(tv.tv_sec),
+ static_cast(tv.tv_usec / 1000));
+}
} // namespace wvutil
diff --git a/oemcrypto/opk/ports/linux/wtpi_tee_simulator.gyp b/oemcrypto/opk/ports/linux/wtpi_tee_simulator.gyp
index f376eaa..d78a12d 100644
--- a/oemcrypto/opk/ports/linux/wtpi_tee_simulator.gyp
+++ b/oemcrypto/opk/ports/linux/wtpi_tee_simulator.gyp
@@ -46,7 +46,6 @@
'<(platform_specific_dir)/file_store.cpp',
'<(platform_specific_dir)/log.cpp',
'<(util_dir)/src/platform.cpp',
- '<(util_dir)/src/rw_lock.cpp',
'<(util_dir)/src/string_conversions.cpp',
'<(util_dir)/src/string_format.cpp',
],
diff --git a/oemcrypto/opk/ports/optee/ta/common/wtpi_impl/genkeypair_ecc.c b/oemcrypto/opk/ports/optee/ta/common/wtpi_impl/genkeypair_ecc.c
index 2c0fd9a..9a62998 100644
--- a/oemcrypto/opk/ports/optee/ta/common/wtpi_impl/genkeypair_ecc.c
+++ b/oemcrypto/opk/ports/optee/ta/common/wtpi_impl/genkeypair_ecc.c
@@ -3,7 +3,6 @@
* source code may only be used and distributed under the Widevine
* License Agreement.
*/
-
#include "asymmetric_key.h"
#include "crypto_util.h"
#include "oemcrypto_check_macros.h"
@@ -31,6 +30,7 @@ static OEMCryptoResult NewEccKeyPair(uint8_t* private_key_data,
TEE_Attribute attr;
TEE_InitValueAttribute(&attr, TEE_ATTR_ECC_CURVE, curve_type, 0);
+
tee_res = TEE_GenerateKey(key, KEY_SIZE_256 * 8, &attr, 1);
if (tee_res != TEE_SUCCESS) {
EMSG("TEE_GenerateKey failed with result 0x%x", tee_res);
diff --git a/oemcrypto/opk/ports/trusty/ta/reference/rustfmt.toml b/oemcrypto/opk/ports/trusty/ta/reference/rustfmt.toml
new file mode 100644
index 0000000..cefaa42
--- /dev/null
+++ b/oemcrypto/opk/ports/trusty/ta/reference/rustfmt.toml
@@ -0,0 +1,5 @@
+# Android Format Style
+
+edition = "2021"
+use_small_heuristics = "Max"
+newline_style = "Unix"
diff --git a/oemcrypto/opk/serialization/common/GEN_common_serializer.c b/oemcrypto/opk/serialization/common/GEN_common_serializer.c
index fed33e1..d44bab7 100644
--- a/oemcrypto/opk/serialization/common/GEN_common_serializer.c
+++ b/oemcrypto/opk/serialization/common/GEN_common_serializer.c
@@ -116,13 +116,13 @@ bool Is_Valid_OEMCryptoResult(uint32_t value) {
}
}
-bool Is_Valid_OEMCrypto_Usage_Entry_Status(uint32_t value) {
+bool Is_Valid_OEMCrypto_UsageEntryStatus(uint32_t value) {
switch (value) {
- case 0: /* kUnused */
- case 1: /* kActive */
- case 2: /* kInactive */
- case 3: /* kInactiveUsed */
- case 4: /* kInactiveUnused */
+ case 0: /* OEMCrypto_Unused */
+ case 1: /* OEMCrypto_Active */
+ case 2: /* OEMCrypto_Inactive */
+ case 3: /* OEMCrypto_InactiveUsed */
+ case 4: /* OEMCrypto_InactiveUnused */
return true;
default:
return false;
@@ -151,8 +151,8 @@ bool Is_Valid_OEMCrypto_LicenseType(uint32_t value) {
bool Is_Valid_OEMCrypto_PrivateKeyType(uint32_t value) {
switch (value) {
- case 0: /* OEMCrypto_RSA_Private_Key */
- case 1: /* OEMCrypto_ECC_Private_Key */
+ case 0: /* OEMCrypto_RSAPrivateKey */
+ case 1: /* OEMCrypto_ECCPrivateKey */
return true;
default:
return false;
@@ -161,9 +161,33 @@ bool Is_Valid_OEMCrypto_PrivateKeyType(uint32_t value) {
bool Is_Valid_OEMCrypto_TimerDelayBase(uint32_t value) {
switch (value) {
- case 0: /* OEMCrypto_License_Start */
- case 1: /* OEMCrypto_License_Load */
- case 2: /* OEMCrypto_First_Decrypt */
+ case 0: /* OEMCrypto_LicenseStart */
+ case 1: /* OEMCrypto_LicenseLoad */
+ case 2: /* OEMCrypto_FirstDecrypt */
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Is_Valid_OEMCrypto_ClockSecurityLevel(uint32_t value) {
+ switch (value) {
+ case 0: /* OEMCrypto_InsecureClock */
+ case 1: /* OEMCrypto_MonotonicClock */
+ case 2: /* OEMCrypto_SecureClock */
+ case 3: /* OEMCrypto_HardwareSecureClock */
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Is_Valid_OEMCrypto_DeCENC_Mitigation_Option(uint32_t value) {
+ switch (value) {
+ case 0: /* OEMCrypto_DeCENC_Mitigation_Option_None */
+ case 1: /* OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream */
+ case 2: /* OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream */
+ case 4: /* OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding */
return true;
default:
return false;
@@ -208,18 +232,6 @@ bool Is_Valid_OEMCrypto_Algorithm(uint32_t value) {
}
}
-bool Is_Valid_OEMCrypto_Clock_Security_Level(uint32_t value) {
- switch (value) {
- case 0: /* kInsecureClock */
- case 1: /* kMonotonicClock */
- case 2: /* kSecureClock */
- case 3: /* kHardwareSecureClock */
- return true;
- default:
- return false;
- }
-}
-
bool Is_Valid_OEMCrypto_HDCP_Capability(uint32_t value) {
switch (value) {
case 0: /* HDCP_NONE */
@@ -385,6 +397,29 @@ void OPK_Pack_OEMCrypto_KeyObject(ODK_Message* msg,
(const OEMCrypto_Substring*)&obj->key_control);
}
+void OPK_Pack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo const* obj) {
+ OPK_Pack_OEMCrypto_Substring(
+ msg, (const OEMCrypto_Substring*)&obj->authentication_key);
+ OPK_Pack_OEMCrypto_Substring(
+ msg, (const OEMCrypto_Substring*)&obj->authentication_key_iv);
+}
+
+void OPK_Pack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2 const* obj) {
+ OPK_Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_id);
+ OPK_Pack_OEMCrypto_Substring(msg,
+ (const OEMCrypto_Substring*)&obj->key_data_iv);
+ OPK_Pack_OEMCrypto_Substring(msg, (const OEMCrypto_Substring*)&obj->key_data);
+ OPK_Pack_OEMCrypto_Substring(
+ msg, (const OEMCrypto_Substring*)&obj->key_control_iv);
+ OPK_Pack_OEMCrypto_Substring(msg,
+ (const OEMCrypto_Substring*)&obj->key_control);
+ OPK_Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ msg,
+ (const OEMCrypto_DeCENC_Mitigation_Info*)&obj->decenc_mitigation_info);
+}
+
void OPK_Pack_OEMCrypto_SubSampleDescription(
ODK_Message* msg, OEMCrypto_SubSampleDescription const* obj) {
OPK_Pack_size_t(msg, (const size_t*)&obj->num_bytes_clear);
@@ -513,6 +548,31 @@ void OPK_Unpack_OEMCrypto_KeyObject(ODK_Message* msg,
OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_control);
}
+void OPK_Unpack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo* obj) {
+ OEMCrypto_AuthenticationKeyInfo tmp_obj;
+ if (obj == NULL) {
+ obj = &tmp_obj;
+ }
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->authentication_key);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->authentication_key_iv);
+}
+
+void OPK_Unpack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2* obj) {
+ OEMCrypto_KeyObjectV2 tmp_obj;
+ if (obj == NULL) {
+ obj = &tmp_obj;
+ }
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_id);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_data);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_control_iv);
+ OPK_Unpack_OEMCrypto_Substring(msg, &obj->key_control);
+ OPK_Unpack_OEMCrypto_DeCENC_Mitigation_Info(msg,
+ &obj->decenc_mitigation_info);
+}
+
void OPK_Unpack_OEMCrypto_SubSampleDescription(
ODK_Message* msg, OEMCrypto_SubSampleDescription* obj) {
OEMCrypto_SubSampleDescription tmp_obj;
diff --git a/oemcrypto/opk/serialization/common/GEN_common_serializer.h b/oemcrypto/opk/serialization/common/GEN_common_serializer.h
index 62bbd10..362f4f5 100644
--- a/oemcrypto/opk/serialization/common/GEN_common_serializer.h
+++ b/oemcrypto/opk/serialization/common/GEN_common_serializer.h
@@ -19,15 +19,16 @@ extern "C" {
bool SuccessResult(OEMCryptoResult result);
bool Is_Valid_OEMCryptoResult(uint32_t value);
-bool Is_Valid_OEMCrypto_Usage_Entry_Status(uint32_t value);
+bool Is_Valid_OEMCrypto_UsageEntryStatus(uint32_t value);
bool Is_Valid_OEMCrypto_ProvisioningRenewalType(uint32_t value);
bool Is_Valid_OEMCrypto_LicenseType(uint32_t value);
bool Is_Valid_OEMCrypto_PrivateKeyType(uint32_t value);
bool Is_Valid_OEMCrypto_TimerDelayBase(uint32_t value);
+bool Is_Valid_OEMCrypto_ClockSecurityLevel(uint32_t value);
+bool Is_Valid_OEMCrypto_DeCENC_Mitigation_Option(uint32_t value);
bool Is_Valid_OEMCryptoBufferType(uint32_t value);
bool Is_Valid_OEMCryptoCipherMode(uint32_t value);
bool Is_Valid_OEMCrypto_Algorithm(uint32_t value);
-bool Is_Valid_OEMCrypto_Clock_Security_Level(uint32_t value);
bool Is_Valid_OEMCrypto_HDCP_Capability(uint32_t value);
bool Is_Valid_OEMCrypto_DTCP2_Capability(uint32_t value);
bool Is_Valid_OEMCrypto_ProvisioningMethod(uint32_t value);
@@ -49,6 +50,10 @@ void OPK_Pack_OEMCrypto_DTCP2_CMI_Packet(ODK_Message* msg,
OEMCrypto_DTCP2_CMI_Packet const* obj);
void OPK_Pack_OEMCrypto_KeyObject(ODK_Message* msg,
OEMCrypto_KeyObject const* obj);
+void OPK_Pack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo const* obj);
+void OPK_Pack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2 const* obj);
void OPK_Pack_OEMCrypto_SubSampleDescription(
ODK_Message* msg, OEMCrypto_SubSampleDescription const* obj);
void OPK_Pack_OEMCrypto_CENCEncryptPatternDesc(
@@ -71,6 +76,10 @@ void OPK_Unpack_OEMCrypto_DTCP2_CMI_Descriptor_2(
void OPK_Unpack_OEMCrypto_DTCP2_CMI_Packet(ODK_Message* msg,
OEMCrypto_DTCP2_CMI_Packet* obj);
void OPK_Unpack_OEMCrypto_KeyObject(ODK_Message* msg, OEMCrypto_KeyObject* obj);
+void OPK_Unpack_OEMCrypto_AuthenticationKeyInfo(
+ ODK_Message* msg, OEMCrypto_AuthenticationKeyInfo* obj);
+void OPK_Unpack_OEMCrypto_KeyObjectV2(ODK_Message* msg,
+ OEMCrypto_KeyObjectV2* obj);
void OPK_Unpack_OEMCrypto_SubSampleDescription(
ODK_Message* msg, OEMCrypto_SubSampleDescription* obj);
void OPK_Unpack_OEMCrypto_CENCEncryptPatternDesc(
diff --git a/oemcrypto/opk/serialization/common/common_special_cases.c b/oemcrypto/opk/serialization/common/common_special_cases.c
index 96c0cbe..2d0d1ca 100644
--- a/oemcrypto/opk/serialization/common/common_special_cases.c
+++ b/oemcrypto/opk/serialization/common/common_special_cases.c
@@ -188,3 +188,42 @@ void OPK_Unpack_OEMCrypto_SampleDescription(ODK_Message* msg,
obj->subsamples = subsamples;
}
+
+void OPK_Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info const* obj) {
+ OPK_Pack_uint32_t(
+ msg, (const OEMCrypto_DeCENC_Mitigation_Option*)&obj->mitigation_option);
+ switch (obj->mitigation_option) {
+ case OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream:
+ OPK_Pack_OEMCrypto_AuthenticationKeyInfo(
+ msg, &obj->configuration_options.authentication_key_info);
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream:
+ // No configuration options
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding:
+ // No configuration options
+ break;
+ default:
+ break;
+ }
+}
+
+void OPK_Unpack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info* obj) {
+ OPK_Unpack_uint32_t(msg, &obj->mitigation_option);
+ switch (obj->mitigation_option) {
+ case OEMCrypto_DeCENC_Mitigation_Option_Authenticate_Bitstream:
+ OPK_Unpack_OEMCrypto_AuthenticationKeyInfo(
+ msg, &obj->configuration_options.authentication_key_info);
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Validate_Bitstream:
+ // No configuration options
+ break;
+ case OEMCrypto_DeCENC_Mitigation_Option_Restrict_Decoding:
+ // No configuration options
+ break;
+ default:
+ break;
+ }
+}
diff --git a/oemcrypto/opk/serialization/common/common_special_cases.h b/oemcrypto/opk/serialization/common/common_special_cases.h
index 2385856..9883dc6 100644
--- a/oemcrypto/opk/serialization/common/common_special_cases.h
+++ b/oemcrypto/opk/serialization/common/common_special_cases.h
@@ -15,6 +15,7 @@ extern "C" {
#include
#include "OEMCryptoCENC.h"
+#include "OEMCryptoCENCCommon.h"
#include "odk_message.h"
/*
@@ -35,6 +36,11 @@ void OPK_Pack_OEMCrypto_SampleDescription(
void OPK_Unpack_OEMCrypto_SampleDescription(ODK_Message* msg,
OEMCrypto_SampleDescription* obj);
+void OPK_Pack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info const* obj);
+void OPK_Unpack_OEMCrypto_DeCENC_Mitigation_Info(
+ ODK_Message* msg, OEMCrypto_DeCENC_Mitigation_Info* obj);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/oemcrypto/opk/serialization/common/include/marshaller_base.h b/oemcrypto/opk/serialization/common/include/marshaller_base.h
index bb376ce..ce229fe 100644
--- a/oemcrypto/opk/serialization/common/include/marshaller_base.h
+++ b/oemcrypto/opk/serialization/common/include/marshaller_base.h
@@ -51,6 +51,9 @@ void OPK_Init_OEMCrypto_InputOutputPair(OEMCrypto_InputOutputPair* obj);
void OPK_Init_OEMCrypto_SampleDescription(OEMCrypto_SampleDescription* obj);
+void OPK_Init_OEMCrypto_DeCENC_Mitigation_Info(
+ OEMCrypto_DeCENC_Mitigation_Info* obj);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/oemcrypto/opk/serialization/common/marshaller_base.c b/oemcrypto/opk/serialization/common/marshaller_base.c
index cb72321..97d3954 100644
--- a/oemcrypto/opk/serialization/common/marshaller_base.c
+++ b/oemcrypto/opk/serialization/common/marshaller_base.c
@@ -40,7 +40,6 @@ void OPK_Init_c_str(char** value) {
*value = NULL;
}
}
-
void OPK_Init_uint8_t(uint8_t* value) {
if (value) {
*value = ~0;
@@ -106,3 +105,11 @@ void OPK_Init_OEMCrypto_SampleDescription(OEMCrypto_SampleDescription* obj) {
OPK_Init_OEMCrypto_InputOutputPair((OEMCrypto_InputOutputPair*)&obj->buffers);
OPK_InitMemory(&obj->iv[0], sizeof(obj->iv));
}
+
+void OPK_Init_OEMCrypto_DeCENC_Mitigation_Info(
+ OEMCrypto_DeCENC_Mitigation_Info* obj) {
+ if (obj) {
+ memset(obj, 0, sizeof(OEMCrypto_DeCENC_Mitigation_Info));
+ obj->mitigation_option = OEMCrypto_DeCENC_Mitigation_Option_None;
+ }
+}
diff --git a/oemcrypto/opk/serialization/common/shared_buffer_allocator.c b/oemcrypto/opk/serialization/common/shared_buffer_allocator.c
index 1c0efbd..ef457f5 100644
--- a/oemcrypto/opk/serialization/common/shared_buffer_allocator.c
+++ b/oemcrypto/opk/serialization/common/shared_buffer_allocator.c
@@ -122,7 +122,7 @@ void OPK_SharedBuffer_Terminate(void) {
* allocated.
*/
void OPK_SharedBuffer_Reset(void) {
- memset(&allocations_[0], 0, sizeof(allocations_));
+ memset(&allocations_[0], 0, buffer_count_ * sizeof(allocations_[0]));
next_buffer_offset_ = 0;
next_buffer_index_ = 0;
buffer_count_ = 0;
diff --git a/oemcrypto/opk/serialization/os_interfaces/opk_dispatcher.h b/oemcrypto/opk/serialization/os_interfaces/opk_dispatcher.h
index 22e7e76..2759874 100644
--- a/oemcrypto/opk/serialization/os_interfaces/opk_dispatcher.h
+++ b/oemcrypto/opk/serialization/os_interfaces/opk_dispatcher.h
@@ -42,16 +42,16 @@ extern "C" {
* The message delivery protocol must handle timeouts and error conditions.
* Those are out of scope of this function.
*
- * OPK_Initialize() must be called before using OPK_DispatchMesage().
+ * OPK_Initialize() must be called before using OPK_DispatchMessage().
*
* Parameters:
* request - The received message that is to be processed. The caller
- * retains ownership of the request messsage and must release any
+ * retains ownership of the request message and must release any
* memory associated with it after OPK_DispatchMessage returns.
*
* response - A newly created message that should be sent to the REE using
* a message delivery protocol. The caller takes ownership of the request
- * messsage and must release any memory associated with it after
+ * message and must release any memory associated with it after
* OPK_DispatchMessage returns.
*
* Return value:
diff --git a/oemcrypto/opk/serialization/os_interfaces/tos_transport_interface.h b/oemcrypto/opk/serialization/os_interfaces/tos_transport_interface.h
index 7e3087a..44f6e17 100644
--- a/oemcrypto/opk/serialization/os_interfaces/tos_transport_interface.h
+++ b/oemcrypto/opk/serialization/os_interfaces/tos_transport_interface.h
@@ -45,8 +45,8 @@ extern "C" {
* the receive function to get a message, then invokes the dispatcher
* function to process the message, and calls the send function to
* deliver the reply. This allows the trusted app to control the
- * message processing loop. See dispatcher_interface.h for a
- * definition of this interface.
+ * message processing loop. See opk_dispatcher.h for a definition of this
+ * interface.
*
* @{
*/
@@ -69,10 +69,9 @@ typedef enum {
/*
* OPK_TRANSPORT_STATUS_IO_ERROR must be returned from
- * TOS_Transport_SendMessage or TOS_Transport_ReceiveMessage if the
- * transport interface was unable to deliver or receive a message
- * for any reason. The transport implementation should be designed
- * to be robust against communication failures, e.g. by providing
+ * TOS_Transport_SendMessage if the transport interface was unable to deliver
+ * or receive a message for any reason. The transport implementation should be
+ * designed to be robust against communication failures, e.g. by providing
* logic to retry delivery or other techniques if possible. The opk
* library does not make any attempts to improve communication
* reliability using these techniques.
@@ -146,7 +145,7 @@ ODK_Message TOS_Transport_GetRequest(void);
*
* An implementation may opt to allocate the payload buffer of the
* message as shared memory to avoid having to copy the response data
- * into the message at the time it is sent to the TEE.
+ * into the message at the time it is sent to the REE.
*
* A single common payload buffer may be used for both the request and
* response messages. They are used sequentially, i.e. all of the data
diff --git a/oemcrypto/opk/serialization/ree/GEN_oemcrypto_api.c b/oemcrypto/opk/serialization/ree/GEN_oemcrypto_api.c
index 15c484b..4fe967c 100644
--- a/oemcrypto/opk/serialization/ree/GEN_oemcrypto_api.c
+++ b/oemcrypto/opk/serialization/ree/GEN_oemcrypto_api.c
@@ -2777,7 +2777,7 @@ cleanup_and_return:
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetUsageEntryInfo(
- OEMCrypto_SESSION session, OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_SESSION session, OEMCrypto_UsageEntryStatus* status,
int64_t* seconds_since_license_received,
int64_t* seconds_since_first_decrypt) {
pthread_mutex_lock(&api_lock);
@@ -3037,41 +3037,6 @@ cleanup_and_return:
return result;
}
-OEMCRYPTO_API OEMCryptoResult OEMCrypto_InstallOemPrivateKey(
- OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
- const uint8_t* wrapped_private_key, size_t wrapped_private_key_length) {
- pthread_mutex_lock(&api_lock);
- OEMCryptoResult result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
- ODK_Message request = ODK_Message_Create(NULL, 0);
- ODK_Message response = ODK_Message_Create(NULL, 0);
-
- API_Initialize();
- request = OPK_Pack_InstallOemPrivateKey_Request(
- session, key_type, wrapped_private_key, wrapped_private_key_length);
- if (ODK_Message_GetStatus(&request) != MESSAGE_STATUS_OK) {
- if (ODK_Message_GetStatus(&request) == MESSAGE_STATUS_BUFFER_TOO_LARGE) {
- api_result = OEMCrypto_ERROR_BUFFER_TOO_LARGE;
- } else {
- api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
- }
- goto cleanup_and_return;
- }
- response = API_Transact(&request);
- if (api_result != OEMCrypto_SUCCESS) goto cleanup_and_return;
- OPK_Unpack_InstallOemPrivateKey_Response(&response, &result);
-
- if (ODK_Message_GetStatus(&response) != MESSAGE_STATUS_OK) {
- api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
- }
-cleanup_and_return:
- TOS_Transport_ReleaseMessage(&request);
- TOS_Transport_ReleaseMessage(&response);
-
- result = API_CheckResult(result);
- pthread_mutex_unlock(&api_lock);
- return result;
-}
-
OEMCRYPTO_API OEMCryptoResult OEMCrypto_EnterTestMode(void) {
pthread_mutex_lock(&api_lock);
OEMCryptoResult result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -3273,6 +3238,40 @@ cleanup_and_return:
return result;
}
+OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetRandom(
+ OEMCrypto_SharedMemory* random_data, size_t random_data_length) {
+ pthread_mutex_lock(&api_lock);
+ OEMCryptoResult result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
+ ODK_Message request = ODK_Message_Create(NULL, 0);
+ ODK_Message response = ODK_Message_Create(NULL, 0);
+
+ API_Initialize();
+ request = OPK_Pack_GetRandom_Request(random_data, random_data_length);
+ if (ODK_Message_GetStatus(&request) != MESSAGE_STATUS_OK) {
+ if (ODK_Message_GetStatus(&request) == MESSAGE_STATUS_BUFFER_TOO_LARGE) {
+ api_result = OEMCrypto_ERROR_BUFFER_TOO_LARGE;
+ } else {
+ api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
+ }
+ goto cleanup_and_return;
+ }
+ response = API_Transact(&request);
+ if (api_result != OEMCrypto_SUCCESS) goto cleanup_and_return;
+ OPK_Unpack_GetRandom_Response(&response, &result, &random_data,
+ &random_data_length);
+
+ if (ODK_Message_GetStatus(&response) != MESSAGE_STATUS_OK) {
+ api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
+ }
+cleanup_and_return:
+ TOS_Transport_ReleaseMessage(&request);
+ TOS_Transport_ReleaseMessage(&response);
+
+ result = API_CheckResult(result);
+ pthread_mutex_unlock(&api_lock);
+ return result;
+}
+
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_GenerateOTARequest(OEMCrypto_SESSION session, uint8_t* buffer,
size_t* buffer_length, uint32_t use_test_key) {
@@ -3344,6 +3343,41 @@ cleanup_and_return:
return result;
}
+OEMCRYPTO_API OEMCryptoResult OEMCrypto_InstallOemPrivateKey(
+ OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key, size_t wrapped_private_key_length) {
+ pthread_mutex_lock(&api_lock);
+ OEMCryptoResult result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
+ ODK_Message request = ODK_Message_Create(NULL, 0);
+ ODK_Message response = ODK_Message_Create(NULL, 0);
+
+ API_Initialize();
+ request = OPK_Pack_InstallOemPrivateKey_Request(
+ session, key_type, wrapped_private_key, wrapped_private_key_length);
+ if (ODK_Message_GetStatus(&request) != MESSAGE_STATUS_OK) {
+ if (ODK_Message_GetStatus(&request) == MESSAGE_STATUS_BUFFER_TOO_LARGE) {
+ api_result = OEMCrypto_ERROR_BUFFER_TOO_LARGE;
+ } else {
+ api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
+ }
+ goto cleanup_and_return;
+ }
+ response = API_Transact(&request);
+ if (api_result != OEMCrypto_SUCCESS) goto cleanup_and_return;
+ OPK_Unpack_InstallOemPrivateKey_Response(&response, &result);
+
+ if (ODK_Message_GetStatus(&response) != MESSAGE_STATUS_OK) {
+ api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
+ }
+cleanup_and_return:
+ TOS_Transport_ReleaseMessage(&request);
+ TOS_Transport_ReleaseMessage(&response);
+
+ result = API_CheckResult(result);
+ pthread_mutex_unlock(&api_lock);
+ return result;
+}
+
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetEmbeddedDrmCertificate(
uint8_t* public_cert, size_t* public_cert_length) {
pthread_mutex_lock(&api_lock);
diff --git a/oemcrypto/opk/serialization/ree/GEN_ree_serializer.c b/oemcrypto/opk/serialization/ree/GEN_ree_serializer.c
index acb3d21..4b8da44 100644
--- a/oemcrypto/opk/serialization/ree/GEN_ree_serializer.c
+++ b/oemcrypto/opk/serialization/ree/GEN_ree_serializer.c
@@ -2900,7 +2900,7 @@ void OPK_Unpack_ReportUsage_Response(ODK_Message* msg, OEMCryptoResult* result,
}
ODK_Message OPK_Pack_GetUsageEntryInfo_Request(
- OEMCrypto_SESSION session, const OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_SESSION session, const OEMCrypto_UsageEntryStatus* status,
const int64_t* seconds_since_license_received,
const int64_t* seconds_since_first_decrypt) {
uint32_t api_value = 148; /* from _oecc148 */
@@ -2919,7 +2919,7 @@ ODK_Message OPK_Pack_GetUsageEntryInfo_Request(
void OPK_Unpack_GetUsageEntryInfo_Response(
ODK_Message* msg, OEMCryptoResult* result,
- OEMCrypto_Usage_Entry_Status** status,
+ OEMCrypto_UsageEntryStatus** status,
int64_t** seconds_since_license_received,
int64_t** seconds_since_first_decrypt) {
uint32_t api_value = UINT32_MAX;
@@ -2933,7 +2933,7 @@ void OPK_Unpack_GetUsageEntryInfo_Response(
if (SuccessResult(*result)) {
OPK_UnpackNullable_uint32_t(msg, status);
if (*status) {
- if (!Is_Valid_OEMCrypto_Usage_Entry_Status(**status)) {
+ if (!Is_Valid_OEMCrypto_UsageEntryStatus(**status)) {
ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
}
}
@@ -3258,41 +3258,6 @@ void OPK_Unpack_GetDeviceSignedCsrPayload_Response(
}
}
-ODK_Message OPK_Pack_InstallOemPrivateKey_Request(
- OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
- const uint8_t* wrapped_private_key, size_t wrapped_private_key_length) {
- uint32_t api_value = 118; /* from _oecc118 */
- ODK_Message msg = TOS_Transport_GetRequest();
- OPK_Pack_uint32_t(&msg, &api_value);
- uint64_t timestamp = time(0);
- OPK_Pack_uint64_t(&msg, ×tamp);
- OPK_Pack_size_t(&msg, &wrapped_private_key_length);
- OPK_Pack_uint32_t(&msg, &session);
- OPK_Pack_uint32_t(&msg, &key_type);
- OPK_PackMemory(&msg, (const uint8_t*)wrapped_private_key,
- OPK_ToLengthType(wrapped_private_key_length));
- OPK_PackEOM(&msg);
- OPK_SharedBuffer_FinalizePacking();
- return msg;
-}
-
-void OPK_Unpack_InstallOemPrivateKey_Response(ODK_Message* msg,
- OEMCryptoResult* result) {
- uint32_t api_value = UINT32_MAX;
- OPK_Unpack_uint32_t(msg, &api_value);
- if (api_value != 118)
- ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
- OPK_Unpack_uint32_t(msg, result);
- if (!Is_Valid_OEMCryptoResult(*result)) {
- ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
- }
- OPK_UnpackEOM(msg);
-
- if (SuccessResult(*result)) {
- OPK_SharedBuffer_FinalizeUnpacking();
- }
-}
-
ODK_Message OPK_Pack_EnterTestMode_Request(void) {
uint32_t api_value = 140; /* from _oecc140 */
ODK_Message msg = TOS_Transport_GetRequest();
@@ -3493,6 +3458,46 @@ void OPK_Unpack_FreeSecureBuffer_Response(
}
}
+ODK_Message OPK_Pack_GetRandom_Request(
+ const OEMCrypto_SharedMemory* random_data, size_t random_data_length) {
+ uint32_t api_value = 6; /* from _oecc6 */
+ ODK_Message msg = TOS_Transport_GetRequest();
+ OPK_Pack_uint32_t(&msg, &api_value);
+ uint64_t timestamp = time(0);
+ OPK_Pack_uint64_t(&msg, ×tamp);
+ OPK_Pack_size_t(&msg, &random_data_length);
+ OPK_PackSharedBuffer(&msg, random_data, OPK_ToLengthType(random_data_length),
+ /* map */ true, /* copy_in */ false,
+ /* is_output */ true);
+ OPK_PackEOM(&msg);
+ OPK_SharedBuffer_FinalizePacking();
+ return msg;
+}
+
+void OPK_Unpack_GetRandom_Response(ODK_Message* msg, OEMCryptoResult* result,
+ OEMCrypto_SharedMemory** random_data,
+ size_t* random_data_length) {
+ uint32_t api_value = UINT32_MAX;
+ OPK_Unpack_uint32_t(msg, &api_value);
+ if (api_value != 6)
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
+ OPK_Unpack_size_t(msg, random_data_length);
+ OPK_Unpack_uint32_t(msg, result);
+ if (!Is_Valid_OEMCryptoResult(*result)) {
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ }
+ if (SuccessResult(*result)) {
+ OPK_UnpackSharedBuffer(msg, random_data,
+ OPK_FromSizeTPtr(random_data_length),
+ /* map */ false, /* is_output */ true);
+ }
+ OPK_UnpackEOM(msg);
+
+ if (SuccessResult(*result)) {
+ OPK_SharedBuffer_FinalizeUnpacking();
+ }
+}
+
ODK_Message OPK_Pack_OPK_SerializationVersion_Request(
const uint32_t* ree_major, const uint32_t* ree_minor,
const uint32_t* tee_major, const uint32_t* tee_minor) {
@@ -3620,6 +3625,41 @@ void OPK_Unpack_ProcessOTAKeybox_Response(ODK_Message* msg,
}
}
+ODK_Message OPK_Pack_InstallOemPrivateKey_Request(
+ OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key, size_t wrapped_private_key_length) {
+ uint32_t api_value = 118; /* from _oecc118 */
+ ODK_Message msg = TOS_Transport_GetRequest();
+ OPK_Pack_uint32_t(&msg, &api_value);
+ uint64_t timestamp = time(0);
+ OPK_Pack_uint64_t(&msg, ×tamp);
+ OPK_Pack_size_t(&msg, &wrapped_private_key_length);
+ OPK_Pack_uint32_t(&msg, &session);
+ OPK_Pack_uint32_t(&msg, &key_type);
+ OPK_PackMemory(&msg, (const uint8_t*)wrapped_private_key,
+ OPK_ToLengthType(wrapped_private_key_length));
+ OPK_PackEOM(&msg);
+ OPK_SharedBuffer_FinalizePacking();
+ return msg;
+}
+
+void OPK_Unpack_InstallOemPrivateKey_Response(ODK_Message* msg,
+ OEMCryptoResult* result) {
+ uint32_t api_value = UINT32_MAX;
+ OPK_Unpack_uint32_t(msg, &api_value);
+ if (api_value != 118)
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
+ OPK_Unpack_uint32_t(msg, result);
+ if (!Is_Valid_OEMCryptoResult(*result)) {
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ }
+ OPK_UnpackEOM(msg);
+
+ if (SuccessResult(*result)) {
+ OPK_SharedBuffer_FinalizeUnpacking();
+ }
+}
+
ODK_Message OPK_Pack_GetEmbeddedDrmCertificate_Request(
const uint8_t* public_cert, const size_t* public_cert_length) {
uint32_t api_value = 151; /* from _oecc151 */
diff --git a/oemcrypto/opk/serialization/ree/GEN_ree_serializer.h b/oemcrypto/opk/serialization/ree/GEN_ree_serializer.h
index b7f0060..9e60486 100644
--- a/oemcrypto/opk/serialization/ree/GEN_ree_serializer.h
+++ b/oemcrypto/opk/serialization/ree/GEN_ree_serializer.h
@@ -405,12 +405,12 @@ ODK_Message OPK_Pack_ReportUsage_Request(OEMCrypto_SESSION session,
void OPK_Unpack_ReportUsage_Response(ODK_Message* msg, OEMCryptoResult* result,
uint8_t** buffer, size_t** buffer_length);
ODK_Message OPK_Pack_GetUsageEntryInfo_Request(
- OEMCrypto_SESSION session, const OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_SESSION session, const OEMCrypto_UsageEntryStatus* status,
const int64_t* seconds_since_license_received,
const int64_t* seconds_since_first_decrypt);
void OPK_Unpack_GetUsageEntryInfo_Response(
ODK_Message* msg, OEMCryptoResult* result,
- OEMCrypto_Usage_Entry_Status** status,
+ OEMCrypto_UsageEntryStatus** status,
int64_t** seconds_since_license_received,
int64_t** seconds_since_first_decrypt);
ODK_Message OPK_Pack_MoveEntry_Request(OEMCrypto_SESSION session,
@@ -456,11 +456,6 @@ ODK_Message OPK_Pack_GetDeviceSignedCsrPayload_Request(
void OPK_Unpack_GetDeviceSignedCsrPayload_Response(
ODK_Message* msg, OEMCryptoResult* result, uint8_t** signed_csr_payload,
size_t** signed_csr_payload_length);
-ODK_Message OPK_Pack_InstallOemPrivateKey_Request(
- OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
- const uint8_t* wrapped_private_key, size_t wrapped_private_key_length);
-void OPK_Unpack_InstallOemPrivateKey_Response(ODK_Message* msg,
- OEMCryptoResult* result);
ODK_Message OPK_Pack_EnterTestMode_Request(void);
void OPK_Unpack_EnterTestMode_Response(ODK_Message* msg,
OEMCryptoResult* result);
@@ -489,6 +484,11 @@ ODK_Message OPK_Pack_FreeSecureBuffer_Request(
void OPK_Unpack_FreeSecureBuffer_Response(
ODK_Message* msg, OEMCryptoResult* result,
OEMCrypto_DestBufferDesc** output_descriptor);
+ODK_Message OPK_Pack_GetRandom_Request(
+ const OEMCrypto_SharedMemory* random_data, size_t random_data_length);
+void OPK_Unpack_GetRandom_Response(ODK_Message* msg, OEMCryptoResult* result,
+ OEMCrypto_SharedMemory** random_data,
+ size_t* random_data_length);
ODK_Message OPK_Pack_OPK_SerializationVersion_Request(
const uint32_t* ree_major, const uint32_t* ree_minor,
const uint32_t* tee_major, const uint32_t* tee_minor);
@@ -509,6 +509,11 @@ ODK_Message OPK_Pack_ProcessOTAKeybox_Request(OEMCrypto_SESSION session,
uint32_t use_test_key);
void OPK_Unpack_ProcessOTAKeybox_Response(ODK_Message* msg,
OEMCryptoResult* result);
+ODK_Message OPK_Pack_InstallOemPrivateKey_Request(
+ OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type,
+ const uint8_t* wrapped_private_key, size_t wrapped_private_key_length);
+void OPK_Unpack_InstallOemPrivateKey_Response(ODK_Message* msg,
+ OEMCryptoResult* result);
ODK_Message OPK_Pack_GetEmbeddedDrmCertificate_Request(
const uint8_t* public_cert, const size_t* public_cert_length);
void OPK_Unpack_GetEmbeddedDrmCertificate_Response(ODK_Message* msg,
diff --git a/oemcrypto/opk/serialization/tee/GEN_dispatcher.c b/oemcrypto/opk/serialization/tee/GEN_dispatcher.c
index 4192081..0832a51 100644
--- a/oemcrypto/opk/serialization/tee/GEN_dispatcher.c
+++ b/oemcrypto/opk/serialization/tee/GEN_dispatcher.c
@@ -81,6 +81,23 @@ void OPK_Init_OEMCrypto_KeyObject(OEMCrypto_KeyObject* obj) {
OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_control);
}
+void OPK_Init_OEMCrypto_AuthenticationKeyInfo(
+ OEMCrypto_AuthenticationKeyInfo* obj) {
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->authentication_key);
+ OPK_Init_OEMCrypto_Substring(
+ (OEMCrypto_Substring*)&obj->authentication_key_iv);
+}
+
+void OPK_Init_OEMCrypto_KeyObjectV2(OEMCrypto_KeyObjectV2* obj) {
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_id);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_data_iv);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_data);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_control_iv);
+ OPK_Init_OEMCrypto_Substring((OEMCrypto_Substring*)&obj->key_control);
+ OPK_Init_OEMCrypto_DeCENC_Mitigation_Info(
+ (OEMCrypto_DeCENC_Mitigation_Info*)&obj->decenc_mitigation_info);
+}
+
void OPK_Init_OEMCrypto_SubSampleDescription(
OEMCrypto_SubSampleDescription* obj) {
OPK_Init_size_t((size_t*)&obj->num_bytes_clear);
@@ -1628,7 +1645,7 @@ ODK_MessageStatus OPK_DispatchMessage(ODK_Message* request,
{
OEMCrypto_SESSION session;
OPK_Init_uint32_t((uint32_t*)&session);
- OEMCrypto_Usage_Entry_Status* status;
+ OEMCrypto_UsageEntryStatus* status;
OPK_InitPointer((uint8_t**)&status);
int64_t* seconds_since_license_received;
OPK_InitPointer((uint8_t**)&seconds_since_license_received);
@@ -1802,28 +1819,6 @@ ODK_MessageStatus OPK_DispatchMessage(ODK_Message* request,
result, signed_csr_payload, signed_csr_payload_length);
break;
}
- case 118: /* OEMCrypto_InstallOemPrivateKey */
- {
- size_t wrapped_private_key_length;
- OPK_Init_size_t((size_t*)&wrapped_private_key_length);
- OEMCrypto_SESSION session;
- OPK_Init_uint32_t((uint32_t*)&session);
- OEMCrypto_PrivateKeyType key_type;
- OPK_Init_uint32_t((uint32_t*)&key_type);
- uint8_t* wrapped_private_key;
- OPK_InitPointer((uint8_t**)&wrapped_private_key);
- OPK_Unpack_InstallOemPrivateKey_Request(request, &session, &key_type,
- &wrapped_private_key,
- &wrapped_private_key_length);
- if (!ODK_Message_IsValid(request)) goto handle_invalid_request;
- OEMCryptoResult result;
- OPK_Init_uint32_t((uint32_t*)&result);
- LOGD("InstallOemPrivateKey");
- result = OEMCrypto_InstallOemPrivateKey(
- session, key_type, wrapped_private_key, wrapped_private_key_length);
- *response = OPK_Pack_InstallOemPrivateKey_Response(result);
- break;
- }
case 140: /* OEMCrypto_EnterTestMode */
{
OPK_Unpack_EnterTestMode_Request(request);
@@ -1925,6 +1920,22 @@ ODK_MessageStatus OPK_DispatchMessage(ODK_Message* request,
*response = OPK_Pack_FreeSecureBuffer_Response(result, output_descriptor);
break;
}
+ case 6: /* OEMCrypto_GetRandom */
+ {
+ size_t random_data_length;
+ OPK_Init_size_t((size_t*)&random_data_length);
+ OEMCrypto_SharedMemory* random_data;
+ OPK_InitPointer((uint8_t**)&random_data);
+ OPK_Unpack_GetRandom_Request(request, &random_data, &random_data_length);
+ if (!ODK_Message_IsValid(request)) goto handle_invalid_request;
+ OEMCryptoResult result;
+ OPK_Init_uint32_t((uint32_t*)&result);
+ LOGD("GetRandom");
+ result = OEMCrypto_GetRandom(random_data, random_data_length);
+ *response = OPK_Pack_GetRandom_Response(
+ result, OPK_SharedBuffer_NextOutputBuffer(), random_data_length);
+ break;
+ }
case 115: /* OEMCrypto_OPK_SerializationVersion */
{
uint32_t* ree_major = (uint32_t*)OPK_VarAlloc(sizeof(uint32_t));
@@ -1993,6 +2004,28 @@ ODK_MessageStatus OPK_DispatchMessage(ODK_Message* request,
*response = OPK_Pack_ProcessOTAKeybox_Response(result);
break;
}
+ case 118: /* OEMCrypto_InstallOemPrivateKey */
+ {
+ size_t wrapped_private_key_length;
+ OPK_Init_size_t((size_t*)&wrapped_private_key_length);
+ OEMCrypto_SESSION session;
+ OPK_Init_uint32_t((uint32_t*)&session);
+ OEMCrypto_PrivateKeyType key_type;
+ OPK_Init_uint32_t((uint32_t*)&key_type);
+ uint8_t* wrapped_private_key;
+ OPK_InitPointer((uint8_t**)&wrapped_private_key);
+ OPK_Unpack_InstallOemPrivateKey_Request(request, &session, &key_type,
+ &wrapped_private_key,
+ &wrapped_private_key_length);
+ if (!ODK_Message_IsValid(request)) goto handle_invalid_request;
+ OEMCryptoResult result;
+ OPK_Init_uint32_t((uint32_t*)&result);
+ LOGD("InstallOemPrivateKey");
+ result = OEMCrypto_InstallOemPrivateKey(
+ session, key_type, wrapped_private_key, wrapped_private_key_length);
+ *response = OPK_Pack_InstallOemPrivateKey_Response(result);
+ break;
+ }
case 151: /* OEMCrypto_GetEmbeddedDrmCertificate */
{
size_t* public_cert_length = (size_t*)OPK_VarAlloc(sizeof(size_t));
diff --git a/oemcrypto/opk/serialization/tee/GEN_tee_serializer.c b/oemcrypto/opk/serialization/tee/GEN_tee_serializer.c
index 47d4c64..23baaa4 100644
--- a/oemcrypto/opk/serialization/tee/GEN_tee_serializer.c
+++ b/oemcrypto/opk/serialization/tee/GEN_tee_serializer.c
@@ -2380,7 +2380,7 @@ ODK_Message OPK_Pack_ReportUsage_Response(OEMCryptoResult result,
void OPK_Unpack_GetUsageEntryInfo_Request(
ODK_Message* msg, OEMCrypto_SESSION* session,
- OEMCrypto_Usage_Entry_Status** status,
+ OEMCrypto_UsageEntryStatus** status,
int64_t** seconds_since_license_received,
int64_t** seconds_since_first_decrypt) {
uint32_t api_value = UINT32_MAX;
@@ -2390,8 +2390,7 @@ void OPK_Unpack_GetUsageEntryInfo_Request(
uint64_t timestamp;
OPK_Unpack_uint64_t(msg, ×tamp);
OPK_Unpack_uint32_t(msg, session);
- *status =
- (uint32_t*)OPK_UnpackAlloc(msg, sizeof(OEMCrypto_Usage_Entry_Status));
+ *status = (uint32_t*)OPK_UnpackAlloc(msg, sizeof(OEMCrypto_UsageEntryStatus));
*seconds_since_license_received =
(int64_t*)OPK_UnpackAlloc(msg, sizeof(int64_t));
*seconds_since_first_decrypt =
@@ -2401,7 +2400,7 @@ void OPK_Unpack_GetUsageEntryInfo_Request(
}
ODK_Message OPK_Pack_GetUsageEntryInfo_Response(
- OEMCryptoResult result, const OEMCrypto_Usage_Entry_Status* status,
+ OEMCryptoResult result, const OEMCrypto_UsageEntryStatus* status,
const int64_t* seconds_since_license_received,
const int64_t* seconds_since_first_decrypt) {
uint32_t api_value = 148; /* from _oecc148 */
@@ -2647,38 +2646,6 @@ ODK_Message OPK_Pack_GetDeviceSignedCsrPayload_Response(
return msg;
}
-void OPK_Unpack_InstallOemPrivateKey_Request(
- ODK_Message* msg, OEMCrypto_SESSION* session,
- OEMCrypto_PrivateKeyType* key_type, uint8_t** wrapped_private_key,
- size_t* wrapped_private_key_length) {
- uint32_t api_value = UINT32_MAX;
- OPK_Unpack_uint32_t(msg, &api_value);
- if (api_value != 118)
- ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
- uint64_t timestamp;
- OPK_Unpack_uint64_t(msg, ×tamp);
- OPK_Unpack_size_t(msg, wrapped_private_key_length);
- OPK_Unpack_uint32_t(msg, session);
- OPK_Unpack_uint32_t(msg, key_type);
- if (!Is_Valid_OEMCrypto_PrivateKeyType(*key_type)) {
- ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
- }
- OPK_UnpackInPlace(msg, (uint8_t**)wrapped_private_key,
- OPK_FromSizeTPtr(wrapped_private_key_length));
- OPK_UnpackEOM(msg);
- OPK_SharedBuffer_FinalizeUnpacking();
-}
-
-ODK_Message OPK_Pack_InstallOemPrivateKey_Response(OEMCryptoResult result) {
- uint32_t api_value = 118; /* from _oecc118 */
- ODK_Message msg = TOS_Transport_GetResponse();
- OPK_Pack_uint32_t(&msg, &api_value);
- OPK_Pack_uint32_t(&msg, &result);
- OPK_PackEOM(&msg);
- OPK_SharedBuffer_FinalizePacking();
- return msg;
-}
-
void OPK_Unpack_EnterTestMode_Request(ODK_Message* msg) {
uint32_t api_value = UINT32_MAX;
OPK_Unpack_uint32_t(msg, &api_value);
@@ -2835,6 +2802,40 @@ ODK_Message OPK_Pack_FreeSecureBuffer_Response(
return msg;
}
+void OPK_Unpack_GetRandom_Request(ODK_Message* msg,
+ OEMCrypto_SharedMemory** random_data,
+ size_t* random_data_length) {
+ uint32_t api_value = UINT32_MAX;
+ OPK_Unpack_uint32_t(msg, &api_value);
+ if (api_value != 6)
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
+ uint64_t timestamp;
+ OPK_Unpack_uint64_t(msg, ×tamp);
+ OPK_Unpack_size_t(msg, random_data_length);
+ OPK_UnpackSharedBuffer(msg, random_data, OPK_FromSizeTPtr(random_data_length),
+ /* map */ true, /* is_output */ true);
+ OPK_UnpackEOM(msg);
+ OPK_SharedBuffer_FinalizeUnpacking();
+}
+
+ODK_Message OPK_Pack_GetRandom_Response(
+ OEMCryptoResult result, const OEMCrypto_SharedMemory* random_data,
+ size_t random_data_length) {
+ uint32_t api_value = 6; /* from _oecc6 */
+ ODK_Message msg = TOS_Transport_GetResponse();
+ OPK_Pack_uint32_t(&msg, &api_value);
+ OPK_Pack_size_t(&msg, &random_data_length);
+ OPK_Pack_uint32_t(&msg, &result);
+ if (SuccessResult(result)) {
+ OPK_PackSharedBuffer(&msg, random_data,
+ OPK_ToLengthType(random_data_length), /* map */ false,
+ /* copy_in */ false, /* is_output */ true);
+ }
+ OPK_PackEOM(&msg);
+ OPK_SharedBuffer_FinalizePacking();
+ return msg;
+}
+
void OPK_Unpack_OPK_SerializationVersion_Request(ODK_Message* msg,
uint32_t** ree_major,
uint32_t** ree_minor,
@@ -2937,6 +2938,38 @@ ODK_Message OPK_Pack_ProcessOTAKeybox_Response(OEMCryptoResult result) {
return msg;
}
+void OPK_Unpack_InstallOemPrivateKey_Request(
+ ODK_Message* msg, OEMCrypto_SESSION* session,
+ OEMCrypto_PrivateKeyType* key_type, uint8_t** wrapped_private_key,
+ size_t* wrapped_private_key_length) {
+ uint32_t api_value = UINT32_MAX;
+ OPK_Unpack_uint32_t(msg, &api_value);
+ if (api_value != 118)
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_API_VALUE_ERROR);
+ uint64_t timestamp;
+ OPK_Unpack_uint64_t(msg, ×tamp);
+ OPK_Unpack_size_t(msg, wrapped_private_key_length);
+ OPK_Unpack_uint32_t(msg, session);
+ OPK_Unpack_uint32_t(msg, key_type);
+ if (!Is_Valid_OEMCrypto_PrivateKeyType(*key_type)) {
+ ODK_MESSAGE_SETSTATUS(msg, MESSAGE_STATUS_INVALID_ENUM_VALUE);
+ }
+ OPK_UnpackInPlace(msg, (uint8_t**)wrapped_private_key,
+ OPK_FromSizeTPtr(wrapped_private_key_length));
+ OPK_UnpackEOM(msg);
+ OPK_SharedBuffer_FinalizeUnpacking();
+}
+
+ODK_Message OPK_Pack_InstallOemPrivateKey_Response(OEMCryptoResult result) {
+ uint32_t api_value = 118; /* from _oecc118 */
+ ODK_Message msg = TOS_Transport_GetResponse();
+ OPK_Pack_uint32_t(&msg, &api_value);
+ OPK_Pack_uint32_t(&msg, &result);
+ OPK_PackEOM(&msg);
+ OPK_SharedBuffer_FinalizePacking();
+ return msg;
+}
+
void OPK_Unpack_GetEmbeddedDrmCertificate_Request(ODK_Message* msg,
uint8_t** public_cert,
size_t** public_cert_length) {
diff --git a/oemcrypto/opk/serialization/tee/GEN_tee_serializer.h b/oemcrypto/opk/serialization/tee/GEN_tee_serializer.h
index 4b3ded9..460c59a 100644
--- a/oemcrypto/opk/serialization/tee/GEN_tee_serializer.h
+++ b/oemcrypto/opk/serialization/tee/GEN_tee_serializer.h
@@ -392,11 +392,11 @@ ODK_Message OPK_Pack_ReportUsage_Response(OEMCryptoResult result,
const size_t* buffer_length);
void OPK_Unpack_GetUsageEntryInfo_Request(
ODK_Message* msg, OEMCrypto_SESSION* session,
- OEMCrypto_Usage_Entry_Status** status,
+ OEMCrypto_UsageEntryStatus** status,
int64_t** seconds_since_license_received,
int64_t** seconds_since_first_decrypt);
ODK_Message OPK_Pack_GetUsageEntryInfo_Response(
- OEMCryptoResult result, const OEMCrypto_Usage_Entry_Status* status,
+ OEMCryptoResult result, const OEMCrypto_UsageEntryStatus* status,
const int64_t* seconds_since_license_received,
const int64_t* seconds_since_first_decrypt);
void OPK_Unpack_MoveEntry_Request(ODK_Message* msg, OEMCrypto_SESSION* session,
@@ -441,11 +441,6 @@ void OPK_Unpack_GetDeviceSignedCsrPayload_Request(
ODK_Message OPK_Pack_GetDeviceSignedCsrPayload_Response(
OEMCryptoResult result, const uint8_t* signed_csr_payload,
const size_t* signed_csr_payload_length);
-void OPK_Unpack_InstallOemPrivateKey_Request(
- ODK_Message* msg, OEMCrypto_SESSION* session,
- OEMCrypto_PrivateKeyType* key_type, uint8_t** wrapped_private_key,
- size_t* wrapped_private_key_length);
-ODK_Message OPK_Pack_InstallOemPrivateKey_Response(OEMCryptoResult result);
void OPK_Unpack_EnterTestMode_Request(ODK_Message* msg);
ODK_Message OPK_Pack_EnterTestMode_Response(OEMCryptoResult result);
void OPK_Unpack_SupportsDecryptHash_Request(ODK_Message* msg);
@@ -470,6 +465,12 @@ void OPK_Unpack_FreeSecureBuffer_Request(
OEMCrypto_DestBufferDesc** output_descriptor, int* secure_fd);
ODK_Message OPK_Pack_FreeSecureBuffer_Response(
OEMCryptoResult result, const OEMCrypto_DestBufferDesc* output_descriptor);
+void OPK_Unpack_GetRandom_Request(ODK_Message* msg,
+ OEMCrypto_SharedMemory** random_data,
+ size_t* random_data_length);
+ODK_Message OPK_Pack_GetRandom_Response(
+ OEMCryptoResult result, const OEMCrypto_SharedMemory* random_data,
+ size_t random_data_length);
void OPK_Unpack_OPK_SerializationVersion_Request(ODK_Message* msg,
uint32_t** ree_major,
uint32_t** ree_minor,
@@ -493,6 +494,11 @@ void OPK_Unpack_ProcessOTAKeybox_Request(ODK_Message* msg,
size_t* buffer_length,
uint32_t* use_test_key);
ODK_Message OPK_Pack_ProcessOTAKeybox_Response(OEMCryptoResult result);
+void OPK_Unpack_InstallOemPrivateKey_Request(
+ ODK_Message* msg, OEMCrypto_SESSION* session,
+ OEMCrypto_PrivateKeyType* key_type, uint8_t** wrapped_private_key,
+ size_t* wrapped_private_key_length);
+ODK_Message OPK_Pack_InstallOemPrivateKey_Response(OEMCryptoResult result);
void OPK_Unpack_GetEmbeddedDrmCertificate_Request(ODK_Message* msg,
uint8_t** public_cert,
size_t** public_cert_length);
diff --git a/oemcrypto/test/Android.mk b/oemcrypto/test/Android.mk
deleted file mode 100644
index 98e9b4d..0000000
--- a/oemcrypto/test/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_C_INCLUDES := \
- vendor/widevine/libwvdrmengine/cdm/util/include \
-
-LOCAL_MODULE:=oemcrypto_test
-LOCAL_LICENSE_KINDS:=legacy_by_exception_only legacy_proprietary
-LOCAL_LICENSE_CONDITIONS:=by_exception_only proprietary by_exception_only
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_OWNER := widevine
-LOCAL_PROPRIETARY_MODULE := true
-
-LOCAL_C_INCLUDES += external/googletest/googlemock/include \
-
-# When built, explicitly put it in the DATA/nativetest directory.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
-
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_MODULE_TARGET_ARCH := arm x86 mips
-endif
-
-include $(LOCAL_PATH)/common.mk
-
-include $(BUILD_EXECUTABLE)
diff --git a/oemcrypto/test/GEN_api_lock_file.c b/oemcrypto/test/GEN_api_lock_file.c
index 9a5af65..91b18b7 100644
--- a/oemcrypto/test/GEN_api_lock_file.c
+++ b/oemcrypto/test/GEN_api_lock_file.c
@@ -213,7 +213,7 @@ OEMCryptoResult _oecc34(void);
OEMCryptoResult _oecc70(uint64_t time_since_license_received,
uint64_t time_since_first_decrypt,
uint64_t time_since_last_decrypt,
- OEMCrypto_Usage_Entry_Status status,
+ OEMCrypto_UsageEntryStatus status,
uint8_t* server_mac_key, uint8_t* client_mac_key,
const uint8_t* pst, size_t pst_length);
OEMCryptoResult _oecc12(OEMCrypto_SESSION session,
@@ -412,7 +412,7 @@ OEMCryptoResult _oecc146(OEMCrypto_SESSION session,
// OEMCrypto_GetUsageEntryInfo defined in v19.0
OEMCryptoResult _oecc148(OEMCrypto_SESSION session,
- OEMCrypto_Usage_Entry_Status* status,
+ OEMCrypto_UsageEntryStatus* status,
int64_t* seconds_since_license_received,
int64_t* seconds_since_first_decrypt);
@@ -450,3 +450,11 @@ OEMCryptoResult _oecc157(OEMCrypto_SESSION session, uint8_t* wrapped_pvr_key,
OEMCryptoResult _oecc158(OEMCrypto_SESSION session,
const uint8_t* wrapped_pvr_key,
size_t wrapped_pvr_key_length);
+
+// OEMCrypto_LoadLicenseData defined in v20.0
+OEMCryptoResult _oecc159(OEMCrypto_SESSION session, const uint8_t* data,
+ size_t data_length);
+
+// OEMCrypto_SaveLicenseData defined in v20.0
+OEMCryptoResult _oecc160(OEMCrypto_SESSION session, uint8_t* data,
+ size_t* data_length);
diff --git a/oemcrypto/test/common.mk b/oemcrypto/test/common.mk
deleted file mode 100644
index 2e9cb1b..0000000
--- a/oemcrypto/test/common.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(filter mips mips64, $(TARGET_ARCH)),)
-# Tests need to be compatible with devices that do not support gnu hash-style
-LOCAL_LDFLAGS+=-Wl,--hash-style=both
-endif
-
-# The unit tests can access v15 functions through the dynamic adapter:
-LOCAL_CFLAGS += -DTEST_OEMCRYPTO_V15
-
-LOCAL_SRC_FILES:= \
- GEN_api_lock_file.c \
- oec_device_features.cpp \
- oec_decrypt_fallback_chain.cpp \
- oec_key_deriver.cpp \
- oec_session_util.cpp \
- oemcrypto_corpus_generator_helper.cpp \
- oemcrypto_session_tests_helper.cpp \
- oemcrypto_basic_test.cpp \
- oemcrypto_cast_test.cpp \
- oemcrypto_decrypt_test.cpp \
- oemcrypto_generic_crypto_test.cpp \
- oemcrypto_license_test.cpp \
- oemcrypto_provisioning_test.cpp \
- oemcrypto_security_test.cpp \
- oemcrypto_usage_table_test.cpp \
- oemcrypto_test.cpp \
- oemcrypto_test_android.cpp \
- oemcrypto_test_main.cpp \
- ota_keybox_test.cpp \
- ../../cdm/util/test/test_sleep.cpp \
- ../util/src/bcc_validator.cpp \
- ../util/src/cbor_validator.cpp \
- ../util/src/device_info_validator.cpp \
- ../util/src/oemcrypto_ecc_key.cpp \
- ../util/src/oemcrypto_rsa_key.cpp \
- ../util/src/prov4_validation_helper.cpp \
- ../util/src/signed_csr_payload_validator.cpp \
- ../util/src/wvcrc.cpp \
-
-LOCAL_C_INCLUDES += \
- $(LOCAL_PATH)/fuzz_tests \
- $(LOCAL_PATH)/../include \
- $(LOCAL_PATH)/../odk/include \
- $(LOCAL_PATH)/../odk/kdo/include \
- $(LOCAL_PATH)/../ref/src \
- $(LOCAL_PATH)/../util/include \
- vendor/widevine/libwvdrmengine/cdm/core/include \
- vendor/widevine/libwvdrmengine/cdm/util/include \
- vendor/widevine/libwvdrmengine/cdm/util/test \
-
-LOCAL_STATIC_LIBRARIES := \
- libcdm \
- libcppbor \
- libjsmn \
- libgmock \
- libgtest \
- libgtest_main \
- libwvlevel3 \
- libcdm_protos \
- libcdm_utils \
- libwv_kdo \
- libwv_odk \
- libPlatformProperties \
-
-LOCAL_SHARED_LIBRARIES := \
- libbase \
- libcrypto \
- libdl \
- libbinder_ndk \
- liblog \
- libmedia_omx \
- libprotobuf-cpp-lite \
- libstagefright_foundation \
- libutils \
- libz \
diff --git a/oemcrypto/test/fuzz_tests/README.md b/oemcrypto/test/fuzz_tests/README.md
index 249fe2f..dd2d683 100644
--- a/oemcrypto/test/fuzz_tests/README.md
+++ b/oemcrypto/test/fuzz_tests/README.md
@@ -96,10 +96,10 @@ typically have less than 1000 executions per second (exec/s).
`LLVMFuzzerInitialize` can be used for global initialization, but there is no
corresponding termination method.
-A good starting example is [`oemcrypto_install_oem_private_key_fuzz.cc`][4].
-Targets should be added to `oemcrypto_opk_fuzztests.gyp` and, if the fuzz test
-applies to partner OEMCrypto implementations, `partner_oemcrypto_fuzztests.gyp`.
-The infrastructure expects that the target name starts with *oemcrypto* and ends
+A good starting example is [`oemcrypto_get_key_handle_fuzz.cc`][4]. Targets
+should be added to `oemcrypto_opk_fuzztests.gyp` and, if the fuzz test applies
+to partner OEMCrypto implementations, `partner_oemcrypto_fuzztests.gyp`. The
+infrastructure expects that the target name starts with *oemcrypto* and ends
with *fuzz*.
For additional information about writing fuzz tests, see
@@ -136,5 +136,5 @@ For additional information about writing fuzz tests, see
[1]: clusterfuzz_setup.md
[2]: https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard
[3]: https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/fuzzer/FuzzedDataProvider.h
-[4]: oemcrypto_install_oem_private_key_fuzz.cc
+[4]: oemcrypto_get_key_handle_fuzz.cc
[5]: https://github.com/google/fuzzing/blob/master/docs/good-fuzz-target.md
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_deactivate_usage_entry_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_deactivate_usage_entry_fuzz.cc
index 9644106..52a269c 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_deactivate_usage_entry_fuzz.cc
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_deactivate_usage_entry_fuzz.cc
@@ -13,7 +13,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
entry.CreateUsageTableHeader();
entry.InstallTestDrmKey();
entry.session().CreateNewUsageEntry();
- entry.session().GenerateNonce();
std::vector encrypted_usage_header;
entry.session().UpdateUsageEntry(&encrypted_usage_header);
// LoadLicense sets the pst for usage entry.
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_fuzz_structs.h b/oemcrypto/test/fuzz_tests/oemcrypto_fuzz_structs.h
index f925b03..f6d6d74 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_fuzz_structs.h
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_fuzz_structs.h
@@ -45,8 +45,6 @@ struct OEMCrypto_Renewal_Response_Fuzz {
struct OEMCrypto_Release_Response_Fuzz {
oemcrypto_core_message::ODK_ReleaseRequest core_request;
- int64_t seconds_since_license_received;
- int64_t seconds_since_first_decrypt;
// license_release_response is of variable length and not included in this
// structure.
};
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_fuzztests.gypi b/oemcrypto/test/fuzz_tests/oemcrypto_fuzztests.gypi
index 187d503..18c917a 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_fuzztests.gypi
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_fuzztests.gypi
@@ -27,9 +27,10 @@
'<(platform_specific_dir)/file_store.cpp',
'<(platform_specific_dir)/log.cpp',
'<(util_dir)/src/platform.cpp',
- '<(util_dir)/src/rw_lock.cpp',
'<(util_dir)/src/string_conversions.cpp',
'<(util_dir)/src/string_format.cpp',
+ '<(util_dir)/src/string_utils.cpp',
+ '<(util_dir)/src/wv_duration.cpp',
'<(util_dir)/test/test_sleep.cpp',
'<(util_dir)/test/test_clock.cpp',
],
@@ -50,7 +51,8 @@
'dependencies': [
'../../../third_party/googletest.gyp:gtest',
'../../../third_party/googletest.gyp:gmock',
- '<(oemcrypto_dir)/util/oec_ref_util.gyp:oec_ref_util',
+ '<(oemcrypto_dir)/util/build.gyp:liboec_ref_util',
+ '<(oemcrypto_dir)/util/wvcrc32.gyp:libwvcrc32',
],
'defines': [
'OEMCRYPTO_FUZZ_TESTS',
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_generate_certificate_key_pair_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_generate_certificate_key_pair_fuzz.cc
index f66353a..cff4bd2 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_generate_certificate_key_pair_fuzz.cc
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_generate_certificate_key_pair_fuzz.cc
@@ -19,38 +19,6 @@ wvoec::OEMCryptoProvisioningAPIFuzz& provisioning_api_fuzz =
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
wvoec::RedirectStdoutToFile();
provisioning_api_fuzz.Initialize();
-
-#ifdef SECOND_STAGE
-
- const uint32_t session_id = provisioning_api_fuzz.session().session_id();
-
- size_t public_key_length = 0;
- size_t public_key_signature_length = 0;
- size_t wrapped_private_key_length = 0;
- OEMCrypto_PrivateKeyType key_type = OEMCrypto_RSA_Private_Key;
- OEMCryptoResult result = OEMCrypto_GenerateCertificateKeyPair(
- session_id, nullptr, &public_key_length, nullptr,
- &public_key_signature_length, nullptr, &wrapped_private_key_length,
- &key_type);
- wvoec::CheckStatusAndExitFuzzerOnFailure(result,
- OEMCrypto_ERROR_SHORT_BUFFER);
-
- std::vector public_key(public_key_length);
- std::vector public_key_signature(public_key_signature_length);
- std::vector wrapped_private_key(wrapped_private_key_length);
- result = OEMCrypto_GenerateCertificateKeyPair(
- session_id, public_key.data(), &public_key_length,
- public_key_signature.data(), &public_key_signature_length,
- wrapped_private_key.data(), &wrapped_private_key_length, &key_type);
- wvoec::CheckStatusAndExitFuzzerOnFailure(result, OEMCrypto_SUCCESS);
-
- result = OEMCrypto_InstallOemPrivateKey(session_id, key_type,
- wrapped_private_key.data(),
- wrapped_private_key_length);
- wvoec::CheckStatusAndExitFuzzerOnFailure(result, OEMCrypto_SUCCESS);
-
-#endif
-
return 0;
}
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_get_random_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_get_random_fuzz.cc
index e81f956..c00a9c9 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_get_random_fuzz.cc
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_get_random_fuzz.cc
@@ -16,7 +16,7 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- std::vector random_data(
+ std::vector random_data(
FuzzedDataProvider(data, size)
.ConsumeIntegralInRange(0, wvoec::MAX_FUZZ_OUTPUT_LENGTH));
OEMCrypto_GetRandom(random_data.data(), random_data.size());
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_install_oem_private_key_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_install_oem_private_key_fuzz.cc
deleted file mode 100644
index 310999c..0000000
--- a/oemcrypto/test/fuzz_tests/oemcrypto_install_oem_private_key_fuzz.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine
-// License Agreement.
-
-#include "FuzzedDataProvider.h"
-#include "OEMCryptoCENC.h"
-#include "oemcrypto_fuzz_helper.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- wvoec::RedirectStdoutToFile();
-
- wvoec::SessionFuzz session_fuzz;
- session_fuzz.Initialize();
- FuzzedDataProvider fuzzed_data(data, size);
- const OEMCrypto_PrivateKeyType key_type = wvoec::ConvertDataToValidEnum(
- fuzzed_data, OEMCrypto_PrivateKeyType_MaxValue);
- const std::vector wrapped_private_key =
- fuzzed_data.ConsumeRemainingBytes();
- OEMCrypto_InstallOemPrivateKey(session_fuzz.session().session_id(), key_type,
- wrapped_private_key.data(),
- wrapped_private_key.size());
- session_fuzz.Terminate();
-
- return 0;
-}
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_opk_dispatcher_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_opk_dispatcher_fuzz.cc
index 231cf40..e270e4f 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_opk_dispatcher_fuzz.cc
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_opk_dispatcher_fuzz.cc
@@ -7,13 +7,13 @@ namespace {
void OpenOEMCryptoTASession() {
uint8_t request_body[] = {
- 0x06, // TAG_UINT32
+ 0x07, // TAG_UINT32
0x09, 0x00, 0x00, 0x00, // API value (0x09)
- 0x07, // TAG_UINT64
+ 0x08, // TAG_UINT64
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
0x01, // TAG_BOOL
0x00, // value (false)
- 0x0a // TAG_EOM
+ 0x0b // TAG_EOM
};
ODK_Message request = ODK_Message_Create(request_body, sizeof(request_body));
ODK_Message_SetSize(&request, sizeof(request_body));
@@ -23,11 +23,11 @@ void OpenOEMCryptoTASession() {
void InitializeOEMCryptoTA() {
uint8_t request_body[] = {
- 0x06, // TAG_UINT32
+ 0x07, // TAG_UINT32
0x01, 0x00, 0x00, 0x00, // API value (0x01)
- 0x07, // TAG_UINT64
+ 0x08, // TAG_UINT64
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
- 0x0a // TAG_EOM
+ 0x0b // TAG_EOM
};
ODK_Message request = ODK_Message_Create(request_body, sizeof(request_body));
ODK_Message_SetSize(&request, sizeof(request_body));
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp b/oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp
index be0ab62..b38a1be 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp
@@ -42,12 +42,8 @@
{
'target_name': 'oemcrypto_opk_dispatcher_fuzz',
'include_dirs': [
- '<(oemcrypto_dir)/opk/serialization/common',
'<(oemcrypto_dir)/opk/serialization/common/include',
'<(oemcrypto_dir)/opk/serialization/os_interfaces',
- '<(oemcrypto_dir)/opk/serialization/tee',
- '<(oemcrypto_dir)/opk/serialization/tee/include',
- '<(oemcrypto_dir)/opk/ports/trusty/include/',
],
'dependencies': [
'<(oemcrypto_dir)/opk/serialization/tee/tee.gyp:opk_tee',
@@ -55,9 +51,9 @@
'sources': [
'oemcrypto_opk_dispatcher_fuzz.cc',
'<(oemcrypto_dir)/opk/serialization/test/tos_secure_buffers.c',
- '<(oemcrypto_dir)/opk/serialization/test/tos_transport_interface.c',
'<(oemcrypto_dir)/opk/serialization/test/tos_logging.c',
- '<(oemcrypto_dir)/opk/ports/trusty/serialization_adapter/shared_memory.c',
+ '<(oemcrypto_dir)/opk/serialization/test/tos_shared_memory.c',
+ '<(oemcrypto_dir)/opk/serialization/test/tos_transport_interface.c',
],
},
{
@@ -67,20 +63,11 @@
],
},
{
- 'target_name': 'oemcrypto_opk_generate_certificate_key_pair_first_stage_fuzz',
+ 'target_name': 'oemcrypto_opk_generate_certificate_key_pair_fuzz',
'sources': [
'oemcrypto_generate_certificate_key_pair_fuzz.cc',
],
},
- {
- 'target_name': 'oemcrypto_opk_generate_certificate_key_pair_second_stage_fuzz',
- 'sources': [
- 'oemcrypto_generate_certificate_key_pair_fuzz.cc',
- ],
- 'defines': [
- 'SECOND_STAGE',
- ],
- },
{
'target_name': 'oemcrypto_opk_generate_rsa_signature_fuzz',
'sources': [
@@ -141,12 +128,6 @@
'oemcrypto_get_random_fuzz.cc',
],
},
- {
- 'target_name': 'oemcrypto_opk_install_oem_private_key_fuzz',
- 'sources': [
- 'oemcrypto_install_oem_private_key_fuzz.cc',
- ],
- },
{
'target_name': 'oemcrypto_opk_license_request_fuzz',
'sources': [
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_release_request_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_release_request_fuzz.cc
index 11df453..77f9079 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_release_request_fuzz.cc
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_release_request_fuzz.cc
@@ -20,7 +20,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
entry.CreateUsageTableHeader();
entry.InstallTestDrmKey();
entry.session().CreateNewUsageEntry();
- entry.session().GenerateNonce();
std::vector encrypted_usage_header;
entry.session().UpdateUsageEntry(&encrypted_usage_header);
entry.LoadLicense();
diff --git a/oemcrypto/test/fuzz_tests/oemcrypto_report_usage_fuzz.cc b/oemcrypto/test/fuzz_tests/oemcrypto_report_usage_fuzz.cc
index 8b63654..cd3923c 100644
--- a/oemcrypto/test/fuzz_tests/oemcrypto_report_usage_fuzz.cc
+++ b/oemcrypto/test/fuzz_tests/oemcrypto_report_usage_fuzz.cc
@@ -21,7 +21,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
entry.CreateUsageTableHeader();
entry.InstallTestDrmKey();
entry.session().CreateNewUsageEntry();
- entry.session().GenerateNonce();
std::vector encrypted_usage_header;
entry.session().UpdateUsageEntry(&encrypted_usage_header);
// Sets pst for usage entry.
diff --git a/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gyp b/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gyp
index 29826b4..b06a7e1 100644
--- a/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gyp
+++ b/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gyp
@@ -44,20 +44,11 @@
],
},
{
- 'target_name': 'oemcrypto_generate_certificate_key_pair_first_stage_fuzz',
+ 'target_name': 'oemcrypto_generate_certificate_key_pair_fuzz',
'sources': [
'oemcrypto_generate_certificate_key_pair_fuzz.cc',
],
},
- {
- 'target_name': 'oemcrypto_generate_certificate_key_pair_second_stage_fuzz',
- 'sources': [
- 'oemcrypto_generate_certificate_key_pair_fuzz.cc',
- ],
- 'defines': [
- 'SECOND_STAGE',
- ],
- },
{
'target_name': 'oemcrypto_generate_rsa_signature_fuzz',
'sources': [
@@ -118,12 +109,6 @@
'oemcrypto_get_random_fuzz.cc',
],
},
- {
- 'target_name': 'oemcrypto_install_oem_private_key_fuzz',
- 'sources': [
- 'oemcrypto_install_oem_private_key_fuzz.cc',
- ],
- },
{
'target_name': 'oemcrypto_license_request_fuzz',
'sources': [
diff --git a/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gypi b/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gypi
index 7252e2f..27e9619 100644
--- a/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gypi
+++ b/oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gypi
@@ -25,7 +25,6 @@
'<(platform_specific_dir)/file_store.cpp',
'<(platform_specific_dir)/log.cpp',
'<(util_dir)/src/platform.cpp',
- '<(util_dir)/src/rw_lock.cpp',
'<(util_dir)/src/string_conversions.cpp',
'<(util_dir)/src/string_format.cpp',
'<(util_dir)/test/test_sleep.cpp',
@@ -49,6 +48,7 @@
'../../../third_party/googletest.gyp:gtest',
'../../../third_party/googletest.gyp:gmock',
'<(oemcrypto_dir)/util/oec_ref_util.gyp:oec_ref_util',
+ '<(oemcrypto_dir)/util/wvcrc32.gyp:libwvcrc32',
],
'defines': [
'OEMCRYPTO_FUZZ_TESTS',
diff --git a/oemcrypto/test/oec_decrypt_fallback_chain.h b/oemcrypto/test/oec_decrypt_fallback_chain.h
index 0bbee74..2be1465 100644
--- a/oemcrypto/test/oec_decrypt_fallback_chain.h
+++ b/oemcrypto/test/oec_decrypt_fallback_chain.h
@@ -31,6 +31,9 @@ namespace wvoec {
// call, we want to test that they correctly reject larger calls.
class DecryptFallbackChain {
public:
+ // There is no reason to have an instance of this class.
+ DecryptFallbackChain() = delete;
+
static OEMCryptoResult Decrypt(
const uint8_t* key_handle, size_t key_handle_length,
const OEMCrypto_SampleDescription* samples, size_t samples_length,
@@ -56,8 +59,6 @@ class DecryptFallbackChain {
const OEMCrypto_CENCEncryptPatternDesc* pattern,
OEMCryptoCipherMode cipher_mode);
- // There is no reason to have an instance of this class.
- DecryptFallbackChain() = delete;
CORE_DISALLOW_COPY_AND_ASSIGN(DecryptFallbackChain);
};
diff --git a/oemcrypto/test/oec_device_features.cpp b/oemcrypto/test/oec_device_features.cpp
index 276e52d..487aba6 100644
--- a/oemcrypto/test/oec_device_features.cpp
+++ b/oemcrypto/test/oec_device_features.cpp
@@ -12,7 +12,6 @@
#include "log.h"
#include "oec_test_data.h"
-#include "string_conversions.h"
#include "test_sleep.h"
namespace wvoec {
@@ -87,7 +86,15 @@ void DeviceFeatures::Initialize() {
printf("supports_cas = %s.\n", supports_cas ? "true" : "false");
OEMCrypto_CloseSession(session);
api_version = OEMCrypto_APIVersion();
- printf("api_version = %u.\n", api_version);
+ const uint32_t minor_version = OEMCrypto_MinorAPIVersion();
+ // This is not exactly right, because it should be the minor version of the
+ // ODK library that has been compiled into OEMCrypto. But that is hard to
+ // discover, and we don't have to get this exactly right for test
+ // purposes. This is only used for information and to skip a few integration
+ // tests.
+ prerelease = (api_version >= 20) && (minor_version == 0);
+ printf("api_version = %u.%u%s.\n", api_version, minor_version,
+ prerelease ? ", (prerelease)" : "");
if (api_version < kCoreMessagesAPI) {
printf("--------- WARNING: minimum API is %d ----------\n", api_version);
printf("--------- Expect most tests will fail. --------\n");
diff --git a/oemcrypto/test/oec_device_features.h b/oemcrypto/test/oec_device_features.h
index 2eb1dd9..78ba3c1 100644
--- a/oemcrypto/test/oec_device_features.h
+++ b/oemcrypto/test/oec_device_features.h
@@ -10,7 +10,7 @@
namespace wvoec {
// These tests are designed to work for this version:
-constexpr unsigned int kCurrentAPI = 19;
+constexpr unsigned int kCurrentAPI = 20;
// The API version when Core Messages were introduced.
constexpr unsigned int kCoreMessagesAPI = 16;
// The API version when we stopped encrypting key control blocks.
@@ -54,6 +54,7 @@ class DeviceFeatures {
bool supports_crc; // Supported decrypt hash type CRC.
bool test_secure_buffers; // If we can create a secure buffer for testing.
bool supports_cas; // Device supports CAS (Condition Access System).
+ bool prerelease; // If the device uses a prerelease version of ODK.
uint32_t api_version;
OEMCrypto_ProvisioningMethod provisioning_method;
diff --git a/oemcrypto/test/oec_session_util.cpp b/oemcrypto/test/oec_session_util.cpp
index 70297a8..b95d3df 100644
--- a/oemcrypto/test/oec_session_util.cpp
+++ b/oemcrypto/test/oec_session_util.cpp
@@ -19,12 +19,13 @@
#include
#include
#include
+#include
#include
+#include
#include
-#include
-#include
#include
+#include
#include
#include
@@ -218,7 +219,7 @@ class boringssl_ptr {
};
Test_PST_Report::Test_PST_Report(const std::string& pst_in,
- OEMCrypto_Usage_Entry_Status status_in)
+ OEMCrypto_UsageEntryStatus status_in)
: status(status_in),
seconds_since_license_received(0),
seconds_since_first_decrypt(0),
@@ -226,129 +227,6 @@ Test_PST_Report::Test_PST_Report(const std::string& pst_in,
pst(pst_in),
time_created(wvutil::Clock().GetCurrentTime()) {}
-template
-OEMCryptoResult
-RoundTrip::
- SignAndCreateRequestWithCustomBufferLengths(bool verify_request) {
- // In the real world, a message should be signed by the client and
- // verified by the server. This simulates that.
- size_t gen_signature_length = 0;
- size_t core_message_length = 0;
- const vector context = session()->GetDefaultContext();
- const size_t small_size = context.size(); // arbitrary.
- if (RequestHasNonce()) {
- session()->GenerateNonce();
- }
- uint32_t session_id = session()->session_id();
- GetDefaultRequestSignatureAndCoreMessageLengths(
- session_id, small_size, &gen_signature_length, &core_message_length);
- // Used to test request APIs with varying lengths of core message.
- core_message_length =
- std::max(core_message_length, required_core_message_size_);
- // Used to test request APIs with varying lengths of signature.
- gen_signature_length =
- std::max(gen_signature_length, required_request_signature_size_);
- // Make the message buffer a little bigger than the core message, or the
- // required size, whichever is larger.
- size_t message_size =
- std::max(required_message_size_, core_message_length + small_size);
- vector data(message_size);
- memcpy(&data[core_message_length], context.data(), context.size());
- for (size_t i = context.size() + core_message_length; i < data.size(); i++) {
- data[i] = i & 0xFF;
- }
- if (ShouldGenerateCorpus()) {
- WriteRequestApiCorpus(gen_signature_length,
- core_message_length, data);
- }
-
- vector gen_signature(gen_signature_length);
- OEMCryptoResult result = PrepAndSignRequest(
- session()->session_id(), data.data(), data.size(), &core_message_length,
- gen_signature.data(), &gen_signature_length);
- // We need to fill in core request and verify signature only for calls other
- // than OEMCryptoMemory buffer overflow test. Any test other than buffer
- // overflow will pass true.
- if (result == OEMCrypto_SUCCESS) {
- gen_signature.resize(gen_signature_length);
- }
- if (!verify_request || result != OEMCrypto_SUCCESS) return result;
- std::string core_message(reinterpret_cast(data.data()),
- core_message_length);
- FillAndVerifyCoreRequest(core_message);
- VerifyRequestSignature(data, gen_signature, core_message_length);
- return result;
-}
-
-template
-void RoundTrip::SetEncryptAndSignResponseLengths() {
- encrypted_response_length_ = encrypted_response_.size();
- response_signature_length_ = response_signature_.size();
-}
-
-template
-void RoundTrip::VerifyEncryptAndSignResponseLengths() const {
- EXPECT_NE(encrypted_response_length_, 0u);
- EXPECT_EQ(encrypted_response_length_, encrypted_response_.size());
- EXPECT_NE(response_signature_length_, 0u);
- EXPECT_EQ(response_signature_length_, response_signature_.size());
-}
-
-template
-void GetDefaultRequestSignatureAndCoreMessageLengths(
- uint32_t& session_id, const size_t& small_size,
- size_t* gen_signature_length, size_t* core_message_length) {
- vector data(small_size);
- for (size_t i = 0; i < data.size(); i++) data[i] = i & 0xFF;
- ASSERT_EQ(
- PrepAndSignRequest(session_id, data.data(), data.size(),
- core_message_length, nullptr, gen_signature_length),
- OEMCrypto_ERROR_SHORT_BUFFER);
-}
-
-template
-void RoundTrip::InjectFuzzedRequestData(uint8_t* data,
- size_t size) {
- OEMCrypto_Request_Fuzz fuzz_structure;
- // Copy data into fuzz structure, cap signature length at 1mb as it will be
- // used to initialize signature vector.
- memcpy(&fuzz_structure, data, sizeof(fuzz_structure));
- fuzz_structure.signature_length =
- std::min(fuzz_structure.signature_length, MB);
- vector signature(fuzz_structure.signature_length);
-
- // Interpret rest of data as actual message buffer to request APIs.
- uint8_t* message_ptr = data + sizeof(fuzz_structure);
- size_t message_size = size - sizeof(fuzz_structure);
- PrepAndSignRequest(session()->session_id(), message_ptr, message_size,
- &fuzz_structure.core_message_length, signature.data(),
- &fuzz_structure.signature_length);
-}
-
-template
-OEMCrypto_Substring RoundTrip::FindSubstring(const void* pointer,
- size_t length) {
- OEMCrypto_Substring substring;
- if (length == 0 || pointer == nullptr) {
- substring.offset = 0;
- substring.length = 0;
- } else {
- substring.offset = reinterpret_cast(pointer) -
- reinterpret_cast(&response_data_);
- substring.length = length;
- }
- return substring;
-}
-
void ProvisioningRoundTrip::PrepareSession(
const wvoec::WidevineKeybox& keybox) {
ASSERT_NO_FATAL_FAILURE(session_->open());
@@ -438,7 +316,7 @@ void ProvisioningRoundTrip::CreateDefaultResponse() {
} else {
response_data_.enc_message_key_length = 0;
}
- core_response_.key_type = OEMCrypto_RSA_Private_Key;
+ core_response_.key_type = OEMCrypto_RSAPrivateKey;
core_response_.enc_private_key =
FindSubstring(response_data_.rsa_key, response_data_.rsa_key_length);
core_response_.enc_private_key_iv = FindSubstring(
@@ -465,8 +343,7 @@ void ProvisioningRoundTrip::
}
void ProvisioningRoundTrip::SignResponse() {
- CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+ CoreMessageFeatures features(kServePrereleaseMessages);
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreProvisioningResponse(
features, core_response_, core_request_, &serialized_core_message_));
// Resizing for huge core message length unit tests.
@@ -581,7 +458,7 @@ void ProvisioningRoundTrip::VerifyLoadFailed() {
ASSERT_EQ(zero, wrapped_rsa_key_);
}
-void Provisioning40RoundTrip::PrepareSession(bool is_oem_key) {
+void Provisioning40TwoStageRoundTrip::PrepareSession(bool is_oem_key) {
const size_t buffer_size = 10240; // Make sure it is large enough.
std::vector public_key(buffer_size);
size_t public_key_size = buffer_size;
@@ -610,7 +487,7 @@ void Provisioning40RoundTrip::PrepareSession(bool is_oem_key) {
}
}
-void Provisioning40RoundTrip::FillAndVerifyCoreRequest(
+void Provisioning40TwoStageRoundTrip::FillAndVerifyCoreRequest(
const std::string& core_message_string) {
EXPECT_TRUE(
oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage(
@@ -620,7 +497,7 @@ void Provisioning40RoundTrip::FillAndVerifyCoreRequest(
EXPECT_EQ(session()->session_id(), core_request_.session_id);
}
-void Provisioning40RoundTrip::VerifyRequestSignature(
+void Provisioning40TwoStageRoundTrip::VerifyRequestSignature(
const vector& data, const vector& generated_signature,
size_t /* core_message_length */) {
ASSERT_NO_FATAL_FAILURE(
@@ -628,7 +505,7 @@ void Provisioning40RoundTrip::VerifyRequestSignature(
generated_signature.size(), kSign_RSASSA_PSS));
}
-OEMCryptoResult Provisioning40RoundTrip::LoadOEMCertResponse() {
+OEMCryptoResult Provisioning40TwoStageRoundTrip::LoadOEMCertResponse() {
EXPECT_GE(wrapped_oem_key_.size(), 0UL);
return OEMCrypto_InstallOemPrivateKey(
session()->session_id(), oem_key_type_,
@@ -636,14 +513,14 @@ OEMCryptoResult Provisioning40RoundTrip::LoadOEMCertResponse() {
wrapped_oem_key_.size());
}
-OEMCryptoResult Provisioning40RoundTrip::LoadDRMCertResponse() {
+OEMCryptoResult Provisioning40TwoStageRoundTrip::LoadDRMCertResponse() {
EXPECT_GE(wrapped_drm_key_.size(), 0UL);
return OEMCrypto_LoadDRMPrivateKey(session()->session_id(), drm_key_type_,
wrapped_drm_key_.data(),
wrapped_drm_key_.size());
}
-void Provisioning40CastRoundTrip::PrepareSession() {
+void Provisioning40OneStageRoundTrip::PrepareSession() {
const size_t buffer_size = 10240; // Make sure it is large enough.
std::vector public_key(buffer_size);
size_t public_key_size = buffer_size;
@@ -666,14 +543,7 @@ void Provisioning40CastRoundTrip::PrepareSession() {
drm_key_type_ = key_type;
}
-void Provisioning40CastRoundTrip::LoadDRMPrivateKey() {
- ASSERT_EQ(OEMCrypto_SUCCESS,
- OEMCrypto_LoadDRMPrivateKey(session()->session_id(), drm_key_type_,
- wrapped_drm_key_.data(),
- wrapped_drm_key_.size()));
-}
-
-void Provisioning40CastRoundTrip::FillAndVerifyCoreRequest(
+void Provisioning40OneStageRoundTrip::FillAndVerifyCoreRequest(
const std::string& core_message_string) {
EXPECT_TRUE(
oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage(
@@ -683,7 +553,62 @@ void Provisioning40CastRoundTrip::FillAndVerifyCoreRequest(
EXPECT_EQ(session()->session_id(), core_request_.session_id);
}
-void Provisioning40CastRoundTrip::VerifyRequestSignature(
+void Provisioning40OneStageRoundTrip::VerifyRequestSignature(
+ const vector& data, const vector& generated_signature,
+ size_t /* core_message_length */) {
+ ASSERT_NO_FATAL_FAILURE(
+ session()->VerifySignature(data, generated_signature.data(),
+ generated_signature.size(), kSign_RSASSA_PSS));
+}
+
+OEMCryptoResult Provisioning40OneStageRoundTrip::LoadDRMCertResponse() {
+ EXPECT_GE(wrapped_drm_key_.size(), 0UL);
+ return OEMCrypto_LoadDRMPrivateKey(session()->session_id(), drm_key_type_,
+ wrapped_drm_key_.data(),
+ wrapped_drm_key_.size());
+}
+
+void Provisioning40CastTwoStageRoundTrip::PrepareSession() {
+ const size_t buffer_size = 10240; // Make sure it is large enough.
+ std::vector public_key(buffer_size);
+ size_t public_key_size = buffer_size;
+ std::vector public_key_signature(buffer_size);
+ size_t public_key_signature_size = buffer_size;
+ std::vector wrapped_private_key(buffer_size);
+ size_t wrapped_private_key_size = buffer_size;
+ OEMCrypto_PrivateKeyType key_type;
+ ASSERT_EQ(
+ OEMCrypto_SUCCESS,
+ OEMCrypto_GenerateCertificateKeyPair(
+ session()->session_id(), public_key.data(), &public_key_size,
+ public_key_signature.data(), &public_key_signature_size,
+ wrapped_private_key.data(), &wrapped_private_key_size, &key_type));
+ wrapped_private_key.resize(wrapped_private_key_size);
+ public_key.resize(public_key_size);
+
+ wrapped_drm_key_ = std::move(wrapped_private_key);
+ drm_public_key_ = std::move(public_key);
+ drm_key_type_ = key_type;
+}
+
+void Provisioning40CastTwoStageRoundTrip::LoadDRMPrivateKey() {
+ ASSERT_EQ(OEMCrypto_SUCCESS,
+ OEMCrypto_LoadDRMPrivateKey(session()->session_id(), drm_key_type_,
+ wrapped_drm_key_.data(),
+ wrapped_drm_key_.size()));
+}
+
+void Provisioning40CastTwoStageRoundTrip::FillAndVerifyCoreRequest(
+ const std::string& core_message_string) {
+ EXPECT_TRUE(
+ oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage(
+ core_message_string, &core_request_));
+ EXPECT_EQ(global_features.api_version, core_request_.api_major_version);
+ EXPECT_EQ(session()->nonce(), core_request_.nonce);
+ EXPECT_EQ(session()->session_id(), core_request_.session_id);
+}
+
+void Provisioning40CastTwoStageRoundTrip::VerifyRequestSignature(
const vector& data, const vector& generated_signature,
size_t /* core_message_length */) {
ASSERT_NO_FATAL_FAILURE(
@@ -692,7 +617,7 @@ void Provisioning40CastRoundTrip::VerifyRequestSignature(
}
// Creates a prov2 response
-void Provisioning40CastRoundTrip::CreateDefaultResponse() {
+void Provisioning40CastTwoStageRoundTrip::CreateDefaultResponse() {
uint32_t algorithm_n = htonl(allowed_schemes_);
memcpy(response_data_.rsa_key, "SIGN", 4);
memcpy(response_data_.rsa_key + 4, &algorithm_n, 4);
@@ -701,7 +626,7 @@ void Provisioning40CastRoundTrip::CreateDefaultResponse() {
response_data_.rsa_key_length = 8 + encoded_rsa_key_.size();
response_data_.nonce = session_->nonce();
response_data_.enc_message_key_length = 0;
- core_response_.key_type = OEMCrypto_RSA_Private_Key;
+ core_response_.key_type = OEMCrypto_RSAPrivateKey;
core_response_.enc_private_key =
FindSubstring(response_data_.rsa_key, response_data_.rsa_key_length);
core_response_.enc_private_key_iv = FindSubstring(
@@ -710,7 +635,7 @@ void Provisioning40CastRoundTrip::CreateDefaultResponse() {
response_data_.enc_message_key, response_data_.enc_message_key_length);
}
-void Provisioning40CastRoundTrip::EncryptAndSignResponse() {
+void Provisioning40CastTwoStageRoundTrip::EncryptAndSignResponse() {
session()->key_deriver().PadAndEncryptProvisioningMessage(
&response_data_, &encrypted_response_data_);
core_response_.enc_private_key.length =
@@ -718,9 +643,8 @@ void Provisioning40CastRoundTrip::EncryptAndSignResponse() {
SignResponse();
}
-void Provisioning40CastRoundTrip::SignResponse() {
- CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
+void Provisioning40CastTwoStageRoundTrip::SignResponse() {
+ CoreMessageFeatures features(kServePrereleaseMessages);
// Create prov 2 request struct from prov 4 request
oemcrypto_core_message::ODK_ProvisioningRequest core_request_prov2;
@@ -760,7 +684,8 @@ void Provisioning40CastRoundTrip::SignResponse() {
SetEncryptAndSignResponseLengths();
}
-OEMCryptoResult Provisioning40CastRoundTrip::LoadResponse(Session* session) {
+OEMCryptoResult Provisioning40CastTwoStageRoundTrip::LoadResponse(
+ Session* session) {
EXPECT_NE(session, nullptr);
// Write corpus for oemcrypto_load_provisioning_fuzz. Fuzz script expects
// unencrypted response from provisioning server as input corpus data.
@@ -787,7 +712,164 @@ OEMCryptoResult Provisioning40CastRoundTrip::LoadResponse(Session* session) {
return sts;
}
-OEMCryptoResult Provisioning40CastRoundTrip::LoadResponseNoRetry(
+OEMCryptoResult Provisioning40CastTwoStageRoundTrip::LoadResponseNoRetry(
+ Session* session, size_t* wrapped_key_length) {
+ EXPECT_NE(session, nullptr);
+ VerifyEncryptAndSignResponseLengths();
+ const std::vector context = session->GetDefaultContext();
+ return OEMCrypto_LoadProvisioningCast(
+ session->session_id(), session->enc_session_key().data(),
+ session->enc_session_key().size(), context.data(), context.size(),
+ encrypted_response_.data(), encrypted_response_.size(),
+ serialized_core_message_.size(), response_signature_.data(),
+ response_signature_.size(), wrapped_rsa_key_.data(), wrapped_key_length);
+}
+
+void Provisioning40CastOneStageRoundTrip::PrepareSession() {
+ const size_t buffer_size = 10240; // Make sure it is large enough.
+ std::vector public_key(buffer_size);
+ size_t public_key_size = buffer_size;
+ std::vector public_key_signature(buffer_size);
+ size_t public_key_signature_size = buffer_size;
+ std::vector wrapped_private_key(buffer_size);
+ size_t wrapped_private_key_size = buffer_size;
+ OEMCrypto_PrivateKeyType key_type;
+ ASSERT_EQ(
+ OEMCrypto_SUCCESS,
+ OEMCrypto_GenerateCertificateKeyPair(
+ session()->session_id(), public_key.data(), &public_key_size,
+ public_key_signature.data(), &public_key_signature_size,
+ wrapped_private_key.data(), &wrapped_private_key_size, &key_type));
+ wrapped_private_key.resize(wrapped_private_key_size);
+ public_key.resize(public_key_size);
+
+ wrapped_drm_key_ = std::move(wrapped_private_key);
+ drm_public_key_ = std::move(public_key);
+ drm_key_type_ = key_type;
+}
+
+void Provisioning40CastOneStageRoundTrip::LoadDRMPrivateKey() {
+ ASSERT_EQ(OEMCrypto_SUCCESS,
+ OEMCrypto_LoadDRMPrivateKey(session()->session_id(), drm_key_type_,
+ wrapped_drm_key_.data(),
+ wrapped_drm_key_.size()));
+}
+
+void Provisioning40CastOneStageRoundTrip::FillAndVerifyCoreRequest(
+ const std::string& core_message_string) {
+ EXPECT_TRUE(
+ oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage(
+ core_message_string, &core_request_));
+ EXPECT_EQ(global_features.api_version, core_request_.api_major_version);
+ EXPECT_EQ(session()->nonce(), core_request_.nonce);
+ EXPECT_EQ(session()->session_id(), core_request_.session_id);
+}
+
+void Provisioning40CastOneStageRoundTrip::VerifyRequestSignature(
+ const vector& data, const vector& generated_signature,
+ size_t /* core_message_length */) {
+ ASSERT_NO_FATAL_FAILURE(
+ session()->VerifySignature(data, generated_signature.data(),
+ generated_signature.size(), kSign_RSASSA_PSS));
+}
+
+// Creates a prov2 response
+void Provisioning40CastOneStageRoundTrip::CreateDefaultResponse() {
+ uint32_t algorithm_n = htonl(allowed_schemes_);
+ memcpy(response_data_.rsa_key, "SIGN", 4);
+ memcpy(response_data_.rsa_key + 4, &algorithm_n, 4);
+ memcpy(response_data_.rsa_key + 8, encoded_rsa_key_.data(),
+ encoded_rsa_key_.size());
+ response_data_.rsa_key_length = 8 + encoded_rsa_key_.size();
+ response_data_.nonce = session_->nonce();
+ response_data_.enc_message_key_length = 0;
+ core_response_.key_type = OEMCrypto_RSAPrivateKey;
+ core_response_.enc_private_key =
+ FindSubstring(response_data_.rsa_key, response_data_.rsa_key_length);
+ core_response_.enc_private_key_iv = FindSubstring(
+ response_data_.rsa_key_iv, sizeof(response_data_.rsa_key_iv));
+ core_response_.encrypted_message_key = FindSubstring(
+ response_data_.enc_message_key, response_data_.enc_message_key_length);
+}
+
+void Provisioning40CastOneStageRoundTrip::EncryptAndSignResponse() {
+ session()->key_deriver().PadAndEncryptProvisioningMessage(
+ &response_data_, &encrypted_response_data_);
+ core_response_.enc_private_key.length =
+ encrypted_response_data_.rsa_key_length;
+ SignResponse();
+}
+
+void Provisioning40CastOneStageRoundTrip::SignResponse() {
+ CoreMessageFeatures features(kServePrereleaseMessages);
+
+ // Create prov 2 request struct from prov 4 request
+ oemcrypto_core_message::ODK_ProvisioningRequest core_request_prov2;
+ core_request_prov2.api_minor_version = core_request_.api_minor_version;
+ core_request_prov2.api_major_version = core_request_.api_major_version;
+ core_request_prov2.nonce = core_request_.nonce;
+ core_request_prov2.session_id = core_request_.session_id;
+ memcpy(&core_request_prov2.counter_info, &core_request_.counter_info,
+ sizeof(core_request_.counter_info));
+
+ ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreProvisioningResponse(
+ features, core_response_, core_request_prov2, &serialized_core_message_));
+ // Resizing for huge core message length unit tests.
+ serialized_core_message_.resize(
+ std::max(required_core_message_size_, serialized_core_message_.size()));
+ // Make the message buffer a just big enough, or the
+ // required size, whichever is larger.
+ const size_t message_size =
+ std::max(required_message_size_, serialized_core_message_.size() +
+ sizeof(encrypted_response_data_));
+ // Stripe the encrypted message.
+ encrypted_response_.resize(message_size);
+ for (size_t i = 0; i < encrypted_response_.size(); i++) {
+ encrypted_response_[i] = i & 0xFF;
+ }
+ ASSERT_GE(encrypted_response_.size(), serialized_core_message_.size());
+ memcpy(encrypted_response_.data(), serialized_core_message_.data(),
+ serialized_core_message_.size());
+ ASSERT_GE(encrypted_response_.size(),
+ serialized_core_message_.size() + sizeof(encrypted_response_data_));
+ memcpy(encrypted_response_.data() + serialized_core_message_.size(),
+ reinterpret_cast(&encrypted_response_data_),
+ sizeof(encrypted_response_data_));
+ session()->key_deriver().ServerSignBuffer(encrypted_response_.data(),
+ encrypted_response_.size(),
+ &response_signature_);
+ SetEncryptAndSignResponseLengths();
+}
+
+OEMCryptoResult Provisioning40CastOneStageRoundTrip::LoadResponse(
+ Session* session) {
+ EXPECT_NE(session, nullptr);
+ // Write corpus for oemcrypto_load_provisioning_fuzz. Fuzz script expects
+ // unencrypted response from provisioning server as input corpus data.
+ // Data will be encrypted and signed again explicitly by fuzzer script after
+ // mutations.
+ if (ShouldGenerateCorpus()) {
+ const std::string file_name =
+ GetFileName("oemcrypto_load_provisioning_fuzz_seed_corpus");
+ // Corpus for license response fuzzer should be in the format:
+ // unencrypted (core_response + response_data).
+ AppendToFile(file_name, reinterpret_cast(&core_response_),
+ sizeof(ODK_ParsedProvisioning));
+ AppendToFile(file_name, reinterpret_cast(&response_data_),
+ sizeof(response_data_));
+ }
+ size_t wrapped_key_length = 0;
+ OEMCryptoResult sts = LoadResponseNoRetry(session, &wrapped_key_length);
+ if (sts != OEMCrypto_ERROR_SHORT_BUFFER) return sts;
+ wrapped_rsa_key_.assign(wrapped_key_length, 0);
+ sts = LoadResponseNoRetry(session, &wrapped_key_length);
+ if (sts == OEMCrypto_SUCCESS) {
+ wrapped_rsa_key_.resize(wrapped_key_length);
+ }
+ return sts;
+}
+
+OEMCryptoResult Provisioning40CastOneStageRoundTrip::LoadResponseNoRetry(
Session* session, size_t* wrapped_key_length) {
EXPECT_NE(session, nullptr);
VerifyEncryptAndSignResponseLengths();
@@ -1002,7 +1084,7 @@ void LicenseRoundTrip::FillCoreResponseSubstrings() {
core_response_.key_array_length = num_keys_;
key_array_.clear();
for (unsigned int i = 0; i < num_keys_; i++) {
- OEMCrypto_KeyObject obj;
+ OEMCrypto_KeyObjectV2 obj;
obj.key_id = FindSubstring(response_data_.keys[i].key_id,
response_data_.keys[i].key_id_length);
obj.key_data_iv = FindSubstring(response_data_.keys[i].key_iv,
@@ -1020,6 +1102,10 @@ void LicenseRoundTrip::FillCoreResponseSubstrings() {
}
obj.key_control = FindSubstring(&response_data_.keys[i].control,
sizeof(response_data_.keys[i].control));
+ obj.decenc_mitigation_info.mitigation_option =
+ OEMCrypto_DeCENC_Mitigation_Option_None;
+ memset(&(obj.decenc_mitigation_info.configuration_options), 0,
+ sizeof(obj.decenc_mitigation_info.configuration_options));
key_array_.push_back(obj);
}
core_response_.key_array = key_array_.data();
@@ -1121,8 +1207,10 @@ void LicenseRoundTrip::EncryptAndSignResponse() {
// We might try to test a future api_version_, but we can only make a core
// message with at most the current ODK version. This is only done to verify
// that OEMCrypto does not attempt to load a future version.
+ const uint32_t api_version =
+ std::min(api_version_, static_cast(ODK_MAJOR_VERSION));
CoreMessageFeatures features = CoreMessageFeatures::DefaultFeatures(
- std::min(api_version_, static_cast(ODK_MAJOR_VERSION)));
+ api_version, kServePrereleaseMessages);
CreateCoreLicenseResponseWithFeatures(features);
SignEncryptedResponse();
}
@@ -1555,8 +1643,8 @@ void RenewalRoundTrip::EncryptAndSignResponse() {
// TODO(b/191724203): Test renewal server has different version from license
// server.
ASSERT_NE(license_messages_, nullptr);
- CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
+ CoreMessageFeatures features = CoreMessageFeatures::DefaultFeatures(
+ license_messages_->api_version(), kServePrereleaseMessages);
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreRenewalResponse(
features, core_request_, renewal_duration_seconds_,
&serialized_core_message_));
@@ -1595,8 +1683,8 @@ void RenewalRoundTrip::InjectFuzzedResponseData(
// TODO(b/191724203): Test renewal server has different version from license
// server.
ASSERT_NE(license_messages_, nullptr);
- CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
+ CoreMessageFeatures features = CoreMessageFeatures::DefaultFeatures(
+ license_messages_->api_version(), kServePrereleaseMessages);
// Serializing core message.
// This call also sets nonce in core response to match with session nonce.
oemcrypto_core_message::serialize::CreateCoreRenewalResponse(
@@ -1673,11 +1761,10 @@ void ReleaseRoundTrip::EncryptAndSignResponse() {
// TODO(b/191724203): Test release server has different version from license
// server.
ASSERT_NE(license_messages_, nullptr);
- CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
+ CoreMessageFeatures features = CoreMessageFeatures::DefaultFeatures(
+ license_messages_->api_version(), kServePrereleaseMessages);
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreReleaseResponse(
- features, core_request_, seconds_since_license_received_,
- seconds_since_first_decrypt_, &serialized_core_message_));
+ features, core_request_, &serialized_core_message_));
// Resize serialize core message to be just big enough or required core
// message size, whichever is larger.
serialized_core_message_.resize(
@@ -1711,14 +1798,12 @@ void ReleaseRoundTrip::InjectFuzzedResponseData(
const OEMCrypto_Release_Response_Fuzz& fuzzed_data,
const uint8_t* release_response, const size_t release_response_size) {
ASSERT_NE(license_messages_, nullptr);
- CoreMessageFeatures features =
- CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
+ CoreMessageFeatures features = CoreMessageFeatures::DefaultFeatures(
+ license_messages_->api_version(), kServePrereleaseMessages);
// Serializing core message.
// This call also sets nonce in core response to match with session nonce.
oemcrypto_core_message::serialize::CreateCoreReleaseResponse(
- features, fuzzed_data.core_request,
- fuzzed_data.seconds_since_license_received,
- fuzzed_data.seconds_since_first_decrypt, &serialized_core_message_);
+ features, fuzzed_data.core_request, &serialized_core_message_);
// Copy serialized core message and encrypted response from data and
// calculate signature. Now we will have a valid signature for data
@@ -1743,10 +1828,6 @@ OEMCryptoResult ReleaseRoundTrip::LoadResponse(Session* session) {
// OEMCrypto_Release_Response_Fuzz + license_release_response.
OEMCrypto_Release_Response_Fuzz release_response_fuzz;
release_response_fuzz.core_request = core_request_;
- release_response_fuzz.seconds_since_license_received =
- seconds_since_license_received_;
- release_response_fuzz.seconds_since_first_decrypt =
- seconds_since_first_decrypt_;
AppendToFile(file_name,
reinterpret_cast(&release_response_fuzz),
sizeof(release_response_fuzz));
@@ -1796,7 +1877,11 @@ void Session::close() {
void Session::GenerateNonce(int* error_counter) {
// We make one attempt. If it fails, we assume there was a nonce flood.
- if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), &nonce_)) {
+ // Using |temp_nonce| to avoid member |nonce_| being modified
+ // during failure.
+ uint32_t temp_nonce = 0;
+ if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), &temp_nonce)) {
+ nonce_ = temp_nonce;
return;
}
if (error_counter) {
@@ -1806,7 +1891,8 @@ void Session::GenerateNonce(int* error_counter) {
// The following is after a 1 second pause, so it cannot be from a nonce
// flood.
ASSERT_EQ(OEMCrypto_SUCCESS,
- OEMCrypto_GenerateNonce(session_id(), &nonce_));
+ OEMCrypto_GenerateNonce(session_id(), &temp_nonce));
+ nonce_ = temp_nonce;
}
}
@@ -2050,11 +2136,11 @@ void Session::SetPublicKeyFromPrivateKeyInfo(OEMCrypto_PrivateKeyType key_type,
const uint8_t* buffer,
size_t length) {
switch (key_type) {
- case OEMCrypto_RSA_Private_Key:
+ case OEMCrypto_RSAPrivateKey:
ASSERT_NO_FATAL_FAILURE(
SetRsaPublicKeyFromPrivateKeyInfo(buffer, length));
return;
- case OEMCrypto_ECC_Private_Key:
+ case OEMCrypto_ECCPrivateKey:
ASSERT_NO_FATAL_FAILURE(
SetEccPublicKeyFromPrivateKeyInfo(buffer, length));
return;
@@ -2079,11 +2165,11 @@ void Session::SetEccPublicKeyFromPrivateKeyInfo(const uint8_t* buffer,
void Session::SetPublicKeyFromSubjectPublicKey(
OEMCrypto_PrivateKeyType key_type, const uint8_t* buffer, size_t length) {
switch (key_type) {
- case OEMCrypto_RSA_Private_Key:
+ case OEMCrypto_RSAPrivateKey:
ASSERT_NO_FATAL_FAILURE(
SetRsaPublicKeyFromSubjectPublicKey(buffer, length));
return;
- case OEMCrypto_ECC_Private_Key:
+ case OEMCrypto_ECCPrivateKey:
ASSERT_NO_FATAL_FAILURE(
SetEccPublicKeyFromSubjectPublicKey(buffer, length));
return;
@@ -2115,18 +2201,22 @@ void Session::VerifyRsaSignature(const vector& message,
FAIL() << "Padding scheme not supported: " << padding_scheme;
return;
}
- const util::RsaSignatureAlgorithm algorithm =
- padding_scheme == kSign_RSASSA_PSS ? util::kRsaPssDefault
- : util::kRsaPkcs1Cast;
- OEMCrypto_SignatureHashAlgorithm hash_algorithm = OEMCrypto_SHA1;
- if (algorithm == util::kRsaPssDefault) {
- ASSERT_THAT(
- OEMCrypto_GetSignatureHashAlgorithm(session_id(), &hash_algorithm),
- AnyOf(OEMCrypto_SUCCESS, OEMCrypto_ERROR_NOT_IMPLEMENTED));
+ util::RsaSignatureAlgorithm algorithm = padding_scheme == kSign_RSASSA_PSS
+ ? util::kRsaPssSha1
+ : util::kRsaPkcs1Cast;
+ if (algorithm == util::kRsaPssSha1) {
+ OEMCrypto_SignatureHashAlgorithm hash_algorithm = OEMCrypto_SHA1;
+ const OEMCryptoResult result =
+ OEMCrypto_GetSignatureHashAlgorithm(session_id(), &hash_algorithm);
+ ASSERT_THAT(result,
+ AnyOf(OEMCrypto_SUCCESS, OEMCrypto_ERROR_NOT_IMPLEMENTED));
+ if (result == OEMCrypto_SUCCESS) {
+ algorithm =
+ util::RsaPssSignatureAlgorithmFromOEMCryptoAlgorithm(hash_algorithm);
+ }
}
- const OEMCryptoResult result =
- public_rsa_->VerifySignature(message.data(), message.size(), signature,
- signature_length, algorithm, hash_algorithm);
+ const OEMCryptoResult result = public_rsa_->VerifySignature(
+ message.data(), message.size(), signature, signature_length, algorithm);
ASSERT_EQ(result, OEMCrypto_SUCCESS) << "RSA signature check failed";
}
@@ -2208,12 +2298,12 @@ void Session::LoadWrappedDrmKey(OEMCrypto_PrivateKeyType key_type,
void Session::LoadWrappedRsaDrmKey(const vector& wrapped_rsa_key) {
ASSERT_NO_FATAL_FAILURE(
- LoadWrappedDrmKey(OEMCrypto_RSA_Private_Key, wrapped_rsa_key));
+ LoadWrappedDrmKey(OEMCrypto_RSAPrivateKey, wrapped_rsa_key));
}
void Session::LoadWrappedEccDrmKey(const vector& wrapped_ecc_key) {
ASSERT_NO_FATAL_FAILURE(
- LoadWrappedDrmKey(OEMCrypto_ECC_Private_Key, wrapped_ecc_key));
+ LoadWrappedDrmKey(OEMCrypto_ECCPrivateKey, wrapped_ecc_key));
}
void Session::CreateNewUsageEntry(OEMCryptoResult* status) {
@@ -2293,8 +2383,8 @@ void Session::GenerateReport(const std::string& pst,
key_deriver_.ClientSignPstReport(pst_report_buffer_, &computed_signature);
EXPECT_EQ(0, memcmp(computed_signature.data(), pst_report().signature(),
SHA_DIGEST_LENGTH));
- EXPECT_GE(kInactiveUnused, pst_report().status());
- EXPECT_GE(kHardwareSecureClock, pst_report().clock_security_level());
+ EXPECT_GE(OEMCrypto_InactiveUnused, pst_report().status());
+ EXPECT_GE(OEMCrypto_HardwareSecureClock, pst_report().clock_security_level());
EXPECT_EQ(pst.length(), pst_report().pst_length());
EXPECT_EQ(0, memcmp(pst.c_str(), pst_report().pst(), pst.length()));
}
@@ -2310,7 +2400,8 @@ void Session::VerifyPST(const Test_PST_Report& expected) {
EXPECT_NEAR(expected.seconds_since_license_received + age,
computed.seconds_since_license_received(), kTimeTolerance);
// Decrypt times only valid on licenses that have been active.
- if (expected.status == kActive || expected.status == kInactiveUsed) {
+ if (expected.status == OEMCrypto_Active ||
+ expected.status == OEMCrypto_InactiveUsed) {
EXPECT_NEAR(expected.seconds_since_first_decrypt + age,
computed.seconds_since_first_decrypt(),
kUsageTableTimeTolerance);
@@ -2354,37 +2445,6 @@ bool ConvertByteToValidBoolean(const bool* in) {
return false;
}
-template
-void WriteRequestApiCorpus(size_t signature_length, size_t core_message_length,
- vector& data) {
- std::string file_name;
- if (std::is_same::value) {
- file_name = GetFileName("oemcrypto_license_request_fuzz_seed_corpus");
- } else if (std::is_same<
- CoreRequest,
- oemcrypto_core_message::ODK_ProvisioningRequest>::value) {
- file_name = GetFileName("oemcrypto_provisioning_request_fuzz_seed_corpus");
- } else if (std::is_same::value) {
- file_name = GetFileName("oemcrypto_renewal_request_fuzz_seed_corpus");
- } else if (std::is_same::value) {
- file_name = GetFileName("oemcrypto_release_request_fuzz_seed_corpus");
- } else {
- LOGE("Invalid CoreRequest type while writing request api corups.");
- }
- // Corpus for request APIs should be signature_length + core_message_length +
- // data pointer.
- OEMCrypto_Request_Fuzz request_fuzz_struct;
- request_fuzz_struct.core_message_length = core_message_length;
- request_fuzz_struct.signature_length = signature_length;
- AppendToFile(file_name, reinterpret_cast(&request_fuzz_struct),
- sizeof(OEMCrypto_Request_Fuzz));
- AppendToFile(file_name, reinterpret_cast(data.data()),
- data.size());
-}
-
OEMCryptoResult GetKeyHandleIntoVector(OEMCrypto_SESSION session,
const uint8_t* key_id,
size_t key_id_length,
diff --git a/oemcrypto/test/oec_session_util.h b/oemcrypto/test/oec_session_util.h
index 3f2ee9a..69280c1 100644
--- a/oemcrypto/test/oec_session_util.h
+++ b/oemcrypto/test/oec_session_util.h
@@ -7,21 +7,29 @@
//
// OEMCrypto unit tests
//
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+
+#include
#include
+#include
#include
+#include
+#include
#include
#include "core_message_deserialize.h"
#include "core_message_features.h"
#include "core_message_serialize.h"
+#include "log.h"
#include "odk.h"
#include "oec_device_features.h"
#include "oec_key_deriver.h"
#include "oemcrypto_ecc_key.h"
+#include "oemcrypto_corpus_generator_helper.h"
#include "oemcrypto_fuzz_structs.h"
#include "oemcrypto_rsa_key.h"
#include "oemcrypto_types.h"
@@ -67,6 +75,8 @@ constexpr int kDefaultKeyIdLength = 16;
constexpr size_t kMaxPSTLength = 255; // In specification.
constexpr size_t kMaxCoreMessage = 200 * kMaxNumKeys + 200; // Rough estimate.
+constexpr bool kServePrereleaseMessages = true;
+
typedef struct {
uint8_t key_id[kTestKeyIdMaxLength];
size_t key_id_length;
@@ -92,9 +102,9 @@ struct MessageData {
struct Test_PST_Report {
Test_PST_Report(const std::string& pst_in,
- OEMCrypto_Usage_Entry_Status status_in);
+ OEMCrypto_UsageEntryStatus status_in);
- OEMCrypto_Usage_Entry_Status status;
+ OEMCrypto_UsageEntryStatus status;
int64_t seconds_since_license_received;
int64_t seconds_since_first_decrypt;
int64_t seconds_since_last_decrypt;
@@ -167,7 +177,7 @@ class RoundTrip {
// Have OEMCrypto sign a request message and then verify the signature and the
// core message.
- virtual void SignAndVerifyRequest() {
+ void SignAndVerifyRequest() {
// Boolean true generates core request and verifies the request.
// Custom message sizes are 0 by default, so the behavior of following
// functions will be sign and verify request without any custom buffers
@@ -177,11 +187,11 @@ class RoundTrip {
}
// Have OEMCrypto sign and call create request APIs. Buffer parameters in API
// can be set to custom values to test with varying lengths of buffers.
- virtual OEMCryptoResult SignAndCreateRequestWithCustomBufferLengths(
+ OEMCryptoResult SignAndCreateRequestWithCustomBufferLengths(
bool verify_request = false);
// Used for OEMCrypto Fuzzing: Function to convert fuzzer data to valid
// License/Provisioning/Renwal request data that can be serialized.
- virtual void InjectFuzzedRequestData(uint8_t* data, size_t size);
+ void InjectFuzzedRequestData(uint8_t* data, size_t size);
// Create a default |response_data| and |core_response|.
virtual void CreateDefaultResponse() = 0;
// Copy fields from |response_data| to |padded_response_data|, encrypting
@@ -191,7 +201,7 @@ class RoundTrip {
// Attempt to load the response and return the error. Short buffer errors are
// handled by LoadResponse, not the caller. All other errors should be
// handled by the caller.
- virtual OEMCryptoResult LoadResponse() { return LoadResponse(session_); }
+ OEMCryptoResult LoadResponse() { return LoadResponse(session_); }
// As with LoadResponse, but load into a different session.
virtual OEMCryptoResult LoadResponse(Session* session) = 0;
@@ -237,7 +247,7 @@ class RoundTrip {
virtual void FillAndVerifyCoreRequest(
const std::string& core_message_string) = 0;
// Find the given pointer in the response_data_.
- virtual OEMCrypto_Substring FindSubstring(const void* pointer, size_t length);
+ OEMCrypto_Substring FindSubstring(const void* pointer, size_t length);
// Set EncryptAndSignResponse output lengths for later verification.
void SetEncryptAndSignResponseLengths();
@@ -265,6 +275,161 @@ class RoundTrip {
size_t response_signature_length_;
};
+template
+void GetDefaultRequestSignatureAndCoreMessageLengths(
+ uint32_t& session_id, const size_t& small_size,
+ size_t* gen_signature_length, size_t* core_message_length) {
+ vector