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 Nov 3, 2023
1 parent 470aadc commit 43fc6bf
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 0 deletions.
1 change: 1 addition & 0 deletions core/drivers/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ srcs-$(CFG_VERSAL_PUF) += versal_puf.c
srcs-$(CFG_VERSAL_HUK) += versal_huk.c
srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c
srcs-$(CFG_RISCV_PLIC) += plic.c
srcs-$(CFG_WIDEVINE_HUK) += widevine_huk.c
subdirs-y += crypto
subdirs-$(CFG_BNXT_FW) += bnxt
subdirs-$(CFG_DRIVERS_CLK) += clk
Expand Down
61 changes: 61 additions & 0 deletions core/drivers/widevine_huk.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2023, The ChromiumOS Authors
*/

#include <kernel/boot.h>
#include <kernel/panic.h>
#include <kernel/tee_common_otp.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
#include <stdbool.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/widevine");
if (node < 0)
return TEE_ERROR_ITEM_NOT_FOUND;

value = fdt_getprop(fdt, node, "optee-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)
{
init_widevine_huk_dt_data();
if (!dt_huk_initialized)
return TEE_ERROR_NO_DATA;

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/boot.h>
#include <kernel/dt.h>
#include <kernel/pseudo_ta.h>
#include <libfdt.h>
#include <malloc.h>
#include <mm/tee_mm.h>
#include <mm/tee_pager.h>
#include <pta_widevine.h>
#include <stdio.h>
#include <string.h>
#include <string_ext.h>
#include <tee_api.h>
#include <trace.h>
#include <util.h>

#define PTA_NAME "widevine.pta"

#define TPM_AUTH_PUB_MAX_SIZE 512
#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 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
* request 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/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, "widevine-root-of-trust", &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;
struct ts_session *session = ts_get_calling_session();

/* Make sure we called from Secure World */
if (!session)
return TEE_ERROR_ACCESS_DENIED;

/* Make sure we 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 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_INOUT,
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;
}

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);
26 changes: 26 additions & 0 deletions lib/libutee/include/pta_widevine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* 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 \
} \
}

/*
* Widevine PTA supported commands
*/
#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 @@ -1063,3 +1063,13 @@ CFG_HMAC_64_1024_RANGE ?= n
# By default use standard pbkdf2 implementation
CFG_CRYPTO_HW_PBKDF2 ?= n
$(eval $(call cfg-depends-all,CFG_CRYPTO_HW_PBKDF2,CFG_CRYPTO_PBKDF2))

# Disable the widevine PTA by default
CFG_WIDEVINE_PTA ?= n

$(eval $(call cfg-depends-all,CFG_WIDEVINE_PTA,CFG_DT))

# Disable the widevine HUK by default
CFG_WIDEVINE_HUK ?= n

$(eval $(call cfg-depends-all,CFG_WIDEVINE_HUK,CFG_DT))

0 comments on commit 43fc6bf

Please sign in to comment.