From dbd5bd2a4d4c45e7e33122151a0996dc846e9c89 Mon Sep 17 00:00:00 2001 From: Matt Feddersen Date: Mon, 27 Mar 2023 19:40:37 -0700 Subject: [PATCH] Update OPK v18 documentation Merge from Widevine repo of http://go/wvgerrit/169050 - Update changelog - Update copy parter files script to include linux port - Update opk_partner_test script (used to make sure everything works out of the box) with third party dependencies, refactored downloads into a public setup.sh script - Remove WTPI_BUILD_INFO from OPK makefiles and gyp files, since it is no longer needed - Remove FILES.md since it is out of date and ree-sources.mk and tee-sources.mk satisfy the same purpose - Add debug flag in comments for OP-TEE and Linux ports. As a hint for how to enable debug in OPK - Remove oemcrypto_build_info.h since it is no longer needed. Move the XSTR macro it contained to oemcrypto_api_macros.h - Add provisioning method macro to OPTEE and Linux build files to hint at how to build Prov 2 and Prov 4 using the same build files but different build-time values. Merged from https://widevine-internal-review.googlesource.com/166219 Bug: 275264353 Test: luci tests Change-Id: I220e3296f631d895a7c4504454635fe396efc0a4 --- libwvdrmengine/oemcrypto/CHANGELOG.md | 161 ++++++++++++++++++ .../oemcrypto/test/GEN_api_lock_file.c | 62 +++++++ 2 files changed, 223 insertions(+) diff --git a/libwvdrmengine/oemcrypto/CHANGELOG.md b/libwvdrmengine/oemcrypto/CHANGELOG.md index 11d38aa0..eef79c27 100644 --- a/libwvdrmengine/oemcrypto/CHANGELOG.md +++ b/libwvdrmengine/oemcrypto/CHANGELOG.md @@ -2,6 +2,167 @@ [TOC] +## [Version 18.1][v18.1] + +OEMCrypto V18.0 consisted of header files only. This release includes tests and +OPK. There have been minor API changes since v18.0, so the version number has +been bumped to 18.1 + +In general, new v18 OEMCrypto features have been implemented in the OPK; since +those have been covered already in the published v18 headers, they will not be +discussed in detail here. + +This OPK release includes OEMCrypto v18 changes outlined in the document "WV +Modular DRM Version 18.1 Delta". In addition, quite a few OPK-specific changes +have been added since the last release. Major changes are described in more +detail below in individual sections, followed by a consolidated list of minor +changes. + +### REE-side hooks + +In oemcrypto/opk/serialization/ree/GEN_oemcrypto_api.c, new ifdef checks have +been added in OEMCrypto_Initialize, OEMCrypto_Terminate, OEMCrypto_DecryptCENC, +and OEMCrypto_LoadLicense. Depending on the macros, liboemcrypto can be compiled +with hooks that execute before, after, or instead of the listed OEMCrypto +functions (or some combination of the three). If a hook macro is defined, the +default behavior is to call that hook function instead of calling into the TEE +-- to do both, at least one more macro must be defined. For more detail, see +GEN_oemcrypto_api.c directly. + +For example, defining the macro `OPK_PRE_HOOK_OEMCRYPTO_DECRYPTCENC` will +execute `OPK_PreHook_OEMCrypto_DecryptCENC()` instead of calling into the TEE. +The same arguments will be passed to this function, which needs a custom +implementation. One use case for this is custom decryption hardware that is +accessible from the REE and can accept opaque decryption key handles intended +for the TEE. The above macro can be used to execute the hook function instead of +calling the TEE, and the hook function can pass the key handle and encrypted +content to the decrypt hardware directly, bypassing the TEE. + +Another example is in `OEMCrypto_Initialize()`. Defining the macro +`OPK_PRE_HOOK_OEMCRYPTO_INITIALIZE` will execute a call to +`OPK_Prehook_OEMCrypto_Initialize()` instead of calling into the TEE. Defining +another macro `OPK_HOOK_AND_USE_TA_OEMCRYPTO_INITIALIZE` will include the call +to the TEE after the pre-hook. The implementer is free to define custom REE-side +initialization logic, and continue to let the TA finish its initialization as +well. + +One more use case: `OEMCrypto_LoadLicense()`. Some implementers have requested +the ability to call a custom function after LoadLicense() returns in order to +parse the license response and control output restrictions accordingly from the +REE (HDCP, watermarking, etc). To do this, define +`OPK_POST_HOOK_OEMCRYPTO_LOAD_LICENSE` and +`OPK_HOOK_AND_USE_TA_OEMCRYPTO_LOAD_LICENSE` at build time and provide +a function implementation for `OPK_Posthook_OEMCrypto_LoadLicense()`. The post +hook function will execute after `OEMCrypto_LoadLicense()` comes back from the +TEE and will use the same function arguments. + +If no macros are defined, there is no change to GEN_oemcrypto_api.c and all +OEMCrypto calls will be forwarded to the TEE without hooks. + +### Configuration macros + +Previously, a platform-specific port needed to define hard coded values in the +implementation of `wtpi_config_interface.h`, as well as macro definitions in +`wtpi_config_macros.h`. These values defined which features were available in +the build, but they were difficult to modify for a new build, and it was often +unclear what configuration values were enabled for a particular build. + +These have been replaced with a single header file consisting of only macro +definitions. For a full list of these configuration macros with default values, +see oemcrypto/opk/oemcrypto_ta/wtpi_reference/config/default.h. + +Each platform-specific port needs to provide configuration values in a file +called `opk_config.h`. The OPK code looks for this file at compilation time. To +provide flexibility at build time, these macro definitions should be `#ifndef` +checked. This way, macros can be defined in the cflags to override the default +values if desired (eg build a version that only changes the provisioning method +by setting the `OPK_CONFIG_PROVISIONING_METHOD` macro in the cflags). The OP-TEE, +Trusty, and Linux reference ports all have `opk_config.h` files that can be used +as examples. + +As part of the OEMCrypto v18 changes, OEMCrypto_BuildInformation() now outputs +JSON-formatted text. If the OPK is built in debug mode, the build information +will also include all of the configuration macro values as a new JSON field. +The intent is to improve the debugging experience by providing as much +configuration information as possible. With the changes to +OEMCrypto_BuildInformation(), the `WTPI_BUILD_INFO` macro is no longer required. + +### OP-TEE port changes + +- Add implementations for provisioning 4.0 WTPI functions. This requires the + third party library open-dice. +- Pre-allocate crypto handles for DecryptCENC. Since this is + a performance-sensitive path, allocate once up front instead of per + DecryptCENC call. +- Reduce compiler warnings. +- Add support for RSA CAST receiver signing. +- Add QEMUv8 target. +- Move der_parse and related files into the wtpi_impl directory. +- Bugfix: Randomly generated ECC key in v17.1 sometimes was smaller than the + expected keysize. Fixed to include leading zeroes if needed. +- Bugfix: WPTI_GenerateRandomCertificateKeyPair() was implemented incorrectly. + It did not return the correct minimum size, used the wrong mbedtls key type, + and did not free allocated resources. Fixed all three issues. + +### Trusty port changes + +In v17.1, the Trusty port did not compile against the OPK. This has been fixed +in v18, with the code moved one directory deeper to a folder named `reference`. + +Implementers looking to create a port based on this reference code are +encouraged to copy the `reference` folder and modify it, instead of modifying +the existing code directly. + +The Trusty port still requires a full download of AOSP Trusty, and must be built +into the Trusty kernel as a user module. In the future we plan to support +standalone TA builds that can be compiled or sideloaded into Trusty OS. + +At this time, there is still no easy way to test builds of the Trusty port +without hardware. QEMU support is planned for a future release. + +### Linux testing port + +A new folder has been created under `oemcrypto/opk/ports` for an implementation +that can run on Linux. Please note that this is a testing-only insecure +implementation, as all code executes in the REE. + +The oemcrypto_unittests and wtpi_unittests applications are the same. The "TA" +is a Linux application that spins a while loop until it receives a message, then +executes that call. The transport interface between liboemcrypto and this fake +TA uses Linux shmem APIs to pass messages back and forth. + +Again, this is not to be used in any kind of production release. The fake TA is +only intended as an easier way to test the REE-TEE code path without a trusted +OS. + +### Other changes + +- Provisioning 4 WTPI functions moved to wtpi_provisioning_4_interface.h. Some + new functions added such as WTPI_GetSignedCsrPayload() +- Provisioning 4 WTPI tests improved to test correctness of BCC and CoseSign1 + payloads, but requires new third party library COSE-C to do so. +- WTPI unit tests can be skipped based on configuration values. Currently + provisioning 4 WTPI functions are skipped if the configured provisioning + method is different. +- Calling an OEMCrypto function with shared buffer arguments could fail if the + underlying buffer was larger than the available shared memory. This would + occur before reaching the TEE in the serialization code, and would return the + default OEMCrypto_ERROR_UNKNOWN_FAILURE error. Now it returns + OEMCrypto_ERROR_BUFFER_TOO_LARGE. +- Fixed a memory leak in the asymmetric key table management code, where key + handles were not freed at session termination. +- Fixed a bug in the serialization code, where `uint8_t iv[16]` parameters were + not passed correctly through to the TEE, eg in AES operations. A NULL input + would always show up as a valid pointer to the TEE. This is now fixed and NULL + inputs show up as NULL in the TEE. + +### Known bugs + +- In the OP-TEE port, WTPI unit tests that use randomly generated ECC keys + occasionally (1/100) fail. The exact cause is unknown, but it appears to be + due to an edge case in the implementation of + WPTI_GenerateRandomCertificateKeyPair(). + ## [Version 17.1][v17.1] This release contains a major change to the build process for the OP-TEE port, diff --git a/libwvdrmengine/oemcrypto/test/GEN_api_lock_file.c b/libwvdrmengine/oemcrypto/test/GEN_api_lock_file.c index 37e577e6..2a29201b 100644 --- a/libwvdrmengine/oemcrypto/test/GEN_api_lock_file.c +++ b/libwvdrmengine/oemcrypto/test/GEN_api_lock_file.c @@ -304,3 +304,65 @@ OEMCryptoResult _oecc120(OEMCrypto_SESSION session, const uint8_t* message, // OEMCrypto_GetOEMKeyToken defined in v17.2 OEMCryptoResult _oecc130(OEMCrypto_SESSION key_session, uint8_t* key_token, size_t* key_token_length); + +// OEMCrypto_SetMaxAPIVersion defined in v18.1 +OEMCryptoResult _oecc132(uint32_t max_version); + +// OEMCrypto_GetKeyHandle defined in v18.1 +OEMCryptoResult _oecc133(OEMCrypto_SESSION session, + const uint8_t* content_key_id, + size_t content_key_id_length, + OEMCryptoCipherMode cipher_mode, uint8_t* key_handle, + size_t* key_handle_length); + +// OEMCrypto_DecryptCENC defined in v18.1 +OEMCryptoResult _oecc134( + const uint8_t* key_handle, size_t key_handle_length, + const OEMCrypto_SampleDescription* samples, // an array of samples. + size_t samples_length, // the number of samples. + const OEMCrypto_CENCEncryptPatternDesc* pattern); + +// OEMCrypto_Generic_Encrypt defined in v18.1 +OEMCryptoResult _oecc135(const uint8_t* key_handle, size_t key_handle_length, + const OEMCrypto_SharedMemory* in_buffer, + size_t in_buffer_length, const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + OEMCrypto_SharedMemory* out_buffer); + +// OEMCrypto_Generic_Decrypt defined in v18.1 +OEMCryptoResult _oecc136(const uint8_t* key_handle, size_t key_handle_length, + const OEMCrypto_SharedMemory* in_buffer, + size_t in_buffer_length, const uint8_t* iv, + OEMCrypto_Algorithm algorithm, + OEMCrypto_SharedMemory* out_buffer); + +// OEMCrypto_Generic_Sign defined in v18.1 +OEMCryptoResult _oecc137(const uint8_t* key_handle, size_t key_handle_length, + const OEMCrypto_SharedMemory* buffer, + size_t buffer_length, OEMCrypto_Algorithm algorithm, + OEMCrypto_SharedMemory* signature, + size_t* signature_length); + +// OEMCrypto_Generic_Verify defined in v18.1 +OEMCryptoResult _oecc138(const uint8_t* key_handle, size_t key_handle_length, + const OEMCrypto_SharedMemory* buffer, + size_t buffer_length, OEMCrypto_Algorithm algorithm, + const OEMCrypto_SharedMemory* signature, + size_t signature_length); + +// OEMCrypto_GetSignatureHashAlgorithm defined in v18.1 +OEMCryptoResult _oecc139(OEMCrypto_SESSION session, + OEMCrypto_SignatureHashAlgorithm* algorithm); + +// OEMCrypto_GetDeviceInformation defined in v18.1 +OEMCryptoResult _oecc131(uint8_t* device_info, size_t* device_info_length); + +// OEMCrypto_GetDeviceSignedCsrPayload defined in v18.1 +OEMCryptoResult _oecc141(const uint8_t* challenge, size_t challenge_length, + const uint8_t* encoded_device_info, + size_t encoded_device_info_length, + uint8_t* signed_csr_payload, + size_t* signed_csr_payload_length); + +// OEMCrypto_EnterTestMode defined in v18.1 +OEMCryptoResult _oecc140(void);