Skip to content

Commit

Permalink
core: pta: widevine: Add the init implementation
Browse files Browse the repository at this point in the history
On the new ChromeOS mediatek platform, we will use the device tree to
pass hardware unique key and the parameters for widevine TAs.

Signed-off-by: Yi Chou <yich@google.com>
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
  • Loading branch information
qazwsxedcrfvtg14 committed Dec 4, 2023
1 parent 01ef3c7 commit 9f85553
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 0 deletions.
2 changes: 2 additions & 0 deletions core/drivers/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ srcs-$(CFG_VERSAL_HUK) += versal_huk.c
srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c
srcs-$(CFG_RISCV_PLIC) += plic.c
srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c
srcs-$(CFG_WIDEVINE_HUK) += widevine_huk.c

subdirs-y += crypto
subdirs-$(CFG_BNXT_FW) += bnxt
subdirs-$(CFG_DRIVERS_CLK) += clk
Expand Down
63 changes: 63 additions & 0 deletions core/drivers/widevine_huk.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2023, The ChromiumOS Authors
*/

#include <kernel/tee_common_otp.h>
#include <libfdt.h>
#include <stdint.h>
#include <string.h>

static uint8_t dt_huk[HW_UNIQUE_KEY_LENGTH];
static bool dt_huk_initialized;

static TEE_Result init_widevine_huk_dt_data(void)
{
int node = 0;
int len = 0;
void *fdt = NULL;
const void *value = NULL;

if (dt_huk_initialized)
return TEE_SUCCESS;

fdt = get_secure_dt();
if (!fdt)
return TEE_ERROR_NO_DATA;

node = fdt_path_offset(fdt, "/options/op-tee/widevine");
if (node < 0)
return TEE_ERROR_ITEM_NOT_FOUND;

value = fdt_getprop(fdt, node, "op-tee,hardware-unique-key", &len);
if (!value)
return TEE_ERROR_ITEM_NOT_FOUND;

if (len >= HW_UNIQUE_KEY_LENGTH)
len = HW_UNIQUE_KEY_LENGTH;
else
return TEE_ERROR_BAD_FORMAT;

dt_huk_initialized = true;

return TEE_SUCCESS;
}

service_init(init_widevine_huk_dt_data);

TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
{
TEE_Result result = TEE_SUCCESS;

/*
* Ensure we get data from the DT, in case called before service_init()
* handler.
*/
result = init_widevine_huk_dt_data();
if (result != TEE_SUCCESS)
return result;

memcpy(hwkey->data, dt_huk, HW_UNIQUE_KEY_LENGTH);

return TEE_SUCCESS;
}
1 change: 1 addition & 0 deletions core/pta/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ srcs-$(CFG_APDU_PTA) += apdu.c
srcs-$(CFG_SCMI_PTA) += scmi.c
srcs-$(CFG_HWRNG_PTA) += hwrng.c
srcs-$(CFG_RTC_PTA) += rtc.c
srcs-$(CFG_WIDEVINE_PTA) += widevine.c

subdirs-y += bcm
subdirs-y += stm32mp
Expand Down
188 changes: 188 additions & 0 deletions core/pta/widevine.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2023, The ChromiumOS Authors
*/

#include <compiler.h>
#include <initcall.h>
#include <kernel/dt.h>
#include <kernel/pseudo_ta.h>
#include <kernel/tee_ta_manager.h>
#include <kernel/ts_manager.h>
#include <libfdt.h>
#include <pta_widevine.h>
#include <stdint.h>
#include <string.h>
#include <tee_api.h>
#include <util.h>

#define PTA_NAME "widevine.pta"

#define TPM_AUTH_PUB_MAX_SIZE 1024
#define WIDEVINE_PRIV_MAX_SIZE 32

#define CROS_HWSEC_TA_UUID \
{ \
0xed800e33, 0x3c58, 0x4cae, \
{ \
0xa7, 0xc0, 0xfd, 0x16, 0x0e, 0x35, 0xe0, 0x0d \
} \
}
#define CROS_HDCP_PROV4_TA_UUID \
{ \
0x0feb839c, 0xee25, 0x4920, \
{ \
0x8e, 0xe3, 0xac, 0x8d, 0xaa, 0x86, 0x0d, 0x3b \
} \
}
#define TA_OPTEE_OEMCRYPTO_UUID \
{ \
0xa92d116c, 0xce27, 0x4917, \
{ \
0xb3, 0x0c, 0x4a, 0x41, 0x6e, 0x2d, 0x93, 0x51 \
} \
}

static const TEE_UUID allowed_ta_uuids[3] = {
CROS_HWSEC_TA_UUID,
CROS_HDCP_PROV4_TA_UUID,
TA_OPTEE_OEMCRYPTO_UUID,
};

/*
* The TPM auth public key. Used to communicate with the TPM from OP-TEE.
* The format of data should be TPM2B_PUBLIC.
* For more information, please reference the 12.2.5 section:
* https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf
*/
static uint8_t tpm_auth_pub[TPM_AUTH_PUB_MAX_SIZE];
static uint32_t tpm_auth_pub_size;

/*
* The Widevine root of trust secret. Used to sign the widevine
* requests in OP-TEE. The value is an ECC NIST P-256 scalar.
* For more information, please reference the G.1.2 section:
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf
*/
static uint8_t widevine_priv[WIDEVINE_PRIV_MAX_SIZE];
static uint32_t widevine_priv_size;

static TEE_Result init_widevine_dt_data(void)
{
int node = 0;
int len = 0;
void *fdt = NULL;
const void *value = NULL;

fdt = get_secure_dt();
if (!fdt)
return TEE_ERROR_NO_DATA;

node = fdt_path_offset(fdt, "/options/op-tee/widevine");
if (node < 0)
return TEE_ERROR_ITEM_NOT_FOUND;

value = fdt_getprop(fdt, node, "tcg,tpm-auth-public-key", &len);
if (!value)
return TEE_ERROR_ITEM_NOT_FOUND;

if (len > TPM_AUTH_PUB_MAX_SIZE)
return TEE_ERROR_OVERFLOW;

memcpy(tpm_auth_pub, value, len);
tpm_auth_pub_size = len;

value = fdt_getprop(fdt, node, "google,widevine-root-of-trust-ecc-p256",
&len);
if (!value)
return TEE_ERROR_ITEM_NOT_FOUND;

if (len > WIDEVINE_PRIV_MAX_SIZE)
return TEE_ERROR_OVERFLOW;

memcpy(widevine_priv, value, len);
widevine_priv_size = len;

return TEE_SUCCESS;
}

service_init(init_widevine_dt_data);

static TEE_Result open_session(uint32_t param_types __unused,
TEE_Param params[TEE_NUM_PARAMS] __unused,
void **sess_ctx __unused)
{
size_t i = 0;
struct ts_session *session = ts_get_calling_session();

/* Make sure we are called from a TA */
if (to_ta_session(ts_get_current_session())->clnt_id.login !=
TEE_LOGIN_TRUSTED_APP)
return TEE_ERROR_ACCESS_DENIED;

/* Make sure we are called from an allowed TA */
for (i = 0; i < ARRAY_SIZE(allowed_ta_uuids); i++)
if (memcmp(&session->ctx->uuid, &allowed_ta_uuids[i],
sizeof(TEE_UUID)) == 0)
return TEE_SUCCESS;

return TEE_ERROR_ACCESS_DENIED;
}

static TEE_Result get_dt_data(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS],
uint32_t cmd)
{
uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
uint8_t *data = NULL;
uint32_t data_length = 0;

if (exp_pt != ptypes)
return TEE_ERROR_BAD_PARAMETERS;

if (cmd == PTA_WIDEVINE_GET_TPM_PUBKEY) {
data = tpm_auth_pub;
data_length = tpm_auth_pub_size;
} else if (cmd == PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY) {
data = widevine_priv;
data_length = widevine_priv_size;
} else {
return TEE_ERROR_NOT_IMPLEMENTED;
}

if (data_length == 0)
return TEE_ERROR_NO_DATA;

if (data_length > params[0].memref.size) {
params[0].memref.size = data_length;
return TEE_ERROR_SHORT_BUFFER;
}

params[0].memref.size = data_length;
memcpy(params[0].memref.buffer, data, data_length);

return TEE_SUCCESS;
}

/*
* Trusted Application Entry Points
*/
static TEE_Result invoke_command(void *psess __unused, uint32_t cmd,
uint32_t ptypes,
TEE_Param params[TEE_NUM_PARAMS])
{
switch (cmd) {
case PTA_WIDEVINE_GET_TPM_PUBKEY:
case PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY:
return get_dt_data(ptypes, params, cmd);
default:
return TEE_ERROR_NOT_IMPLEMENTED;
}
}

pseudo_ta_register(.uuid = PTA_WIDEVINE_UUID, .name = PTA_NAME,
.flags = PTA_DEFAULT_FLAGS,
.open_session_entry_point = open_session,
.invoke_command_entry_point = invoke_command);
36 changes: 36 additions & 0 deletions lib/libutee/include/pta_widevine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2023, The ChromiumOS Authors
*/

#ifndef __PTA_WIDEVINE_H
#define __PTA_WIDEVINE_H

/*
* Interface to the widevine pseudo-TA, which is used for passing parameters
* for widevine TA.
*/
#define PTA_WIDEVINE_UUID \
{ \
0x721f4da9, 0xda05, 0x40d4, \
{ \
0xa1, 0xa3, 0x83, 0x77, 0xc1, 0xe0, 0x8b, 0x0a \
} \
}

/*
* PTA_WIDEVINE_GET_TPM_PUBKEY - Get Widevine TPM public key
* PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY - Get Widevine private key
*
* [out] memref[0] Retrieved key data
*
* Return codes:
* TEE_SUCCESS - Invoke command success
* TEE_ERROR_BAD_PARAMETERS - Incorrect parameters
* TEE_ERROR_SHORT_BUFFER - Output buffer size is too small
* TEE_ERROR_NO_DATA - Requested data not available
*/
#define PTA_WIDEVINE_GET_TPM_PUBKEY 0
#define PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY 1

#endif /* __PTA_WIDEVINE_H */
10 changes: 10 additions & 0 deletions mk/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -1129,3 +1129,13 @@ $(eval $(call cfg-depends-all,CFG_CRYPTO_HW_PBKDF2,CFG_CRYPTO_PBKDF2))
CFG_HALT_CORES_ON_PANIC ?= n
CFG_HALT_CORES_ON_PANIC_SGI ?= 15
$(eval $(call cfg-depends-all,CFG_HALT_CORES_ON_PANIC,CFG_GIC))

# When enabled, CFG_WIDEVINE_HUK uses the widevine HUK provided by secure
# DTB as OP-TEE HUK.
CFG_WIDEVINE_HUK ?= n
$(eval $(call cfg-depends-all,CFG_WIDEVINE_HUK,CFG_DT))

# When enabled, CFG_WIDEVINE_PTA embeds a PTA that exposes the keys under
# DT node "/options/op-tee/widevine" to some specific TAs.
CFG_WIDEVINE_PTA ?= n
$(eval $(call cfg-depends-all,CFG_WIDEVINE_PTA,CFG_DT CFG_WIDEVINE_HUK))

0 comments on commit 9f85553

Please sign in to comment.