1fa0525faSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2fa0525faSJens Wiklander /*
3fa0525faSJens Wiklander * Copyright (c) 2019, Linaro Limited
4fa0525faSJens Wiklander */
5fa0525faSJens Wiklander
633b38f8cSRuslan Piasetskyi #include <config.h>
7fa0525faSJens Wiklander #include <crypto/crypto.h>
8fa0525faSJens Wiklander #include <kernel/huk_subkey.h>
9fa0525faSJens Wiklander #include <kernel/tee_common_otp.h>
103ca4a1caSJerome Forissier #include <string_ext.h>
1117888736SJens Wiklander #include <tee/tee_fs_key_manager.h>
12fa0525faSJens Wiklander
mac_usage(void * ctx,uint32_t usage)13fa0525faSJens Wiklander static TEE_Result mac_usage(void *ctx, uint32_t usage)
14fa0525faSJens Wiklander {
15c69bc615SJens Wiklander return crypto_mac_update(ctx, (const void *)&usage, sizeof(usage));
16fa0525faSJens Wiklander }
17fa0525faSJens Wiklander
1817888736SJens Wiklander #ifdef CFG_CORE_HUK_SUBKEY_COMPAT
get_otp_die_id(uint8_t * buffer,size_t len)1933b38f8cSRuslan Piasetskyi static TEE_Result get_otp_die_id(uint8_t *buffer, size_t len)
2017888736SJens Wiklander {
2117888736SJens Wiklander static const char pattern[4] = { 'B', 'E', 'E', 'F' };
2217888736SJens Wiklander size_t i;
2317888736SJens Wiklander
2433b38f8cSRuslan Piasetskyi if (IS_ENABLED(CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID))
2533b38f8cSRuslan Piasetskyi return tee_otp_get_die_id(buffer, len);
2633b38f8cSRuslan Piasetskyi
2717888736SJens Wiklander for (i = 0; i < len; i++)
2817888736SJens Wiklander buffer[i] = pattern[i % 4];
2933b38f8cSRuslan Piasetskyi
3033b38f8cSRuslan Piasetskyi return TEE_SUCCESS;
3117888736SJens Wiklander }
3217888736SJens Wiklander
3317888736SJens Wiklander /*
3417888736SJens Wiklander * This does special treatment for RPMB and SSK key derivations to give
3517888736SJens Wiklander * the same result as when huk_subkey_derive() wasn't used.
3617888736SJens Wiklander */
huk_compat(void * ctx,enum huk_subkey_usage usage)3717888736SJens Wiklander static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage)
3817888736SJens Wiklander {
3917888736SJens Wiklander TEE_Result res = TEE_SUCCESS;
4017888736SJens Wiklander uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH] = { 0 };
4117888736SJens Wiklander static uint8_t ssk_str[] = "ONLY_FOR_tee_fs_ssk";
4217888736SJens Wiklander
4317888736SJens Wiklander switch (usage) {
4417888736SJens Wiklander case HUK_SUBKEY_RPMB:
4517888736SJens Wiklander return TEE_SUCCESS;
4617888736SJens Wiklander case HUK_SUBKEY_SSK:
4733b38f8cSRuslan Piasetskyi res = get_otp_die_id(chip_id, sizeof(chip_id));
4833b38f8cSRuslan Piasetskyi if (res)
4933b38f8cSRuslan Piasetskyi return res;
50c69bc615SJens Wiklander res = crypto_mac_update(ctx, chip_id, sizeof(chip_id));
5117888736SJens Wiklander if (res)
5217888736SJens Wiklander return res;
53c69bc615SJens Wiklander return crypto_mac_update(ctx, ssk_str, sizeof(ssk_str));
5417888736SJens Wiklander default:
5517888736SJens Wiklander return mac_usage(ctx, usage);
5617888736SJens Wiklander }
5717888736SJens Wiklander
5817888736SJens Wiklander }
5917888736SJens Wiklander #endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/
6017888736SJens Wiklander
__huk_subkey_derive(enum huk_subkey_usage usage,const void * const_data,size_t const_data_len,uint8_t * subkey,size_t subkey_len)61*e6e1a209SThomas Bourgoin TEE_Result __huk_subkey_derive(enum huk_subkey_usage usage,
62fa0525faSJens Wiklander const void *const_data, size_t const_data_len,
63fa0525faSJens Wiklander uint8_t *subkey, size_t subkey_len)
64fa0525faSJens Wiklander {
65fa0525faSJens Wiklander void *ctx = NULL;
66fa0525faSJens Wiklander struct tee_hw_unique_key huk = { };
67fa0525faSJens Wiklander TEE_Result res = TEE_SUCCESS;
68fa0525faSJens Wiklander
69fa0525faSJens Wiklander if (subkey_len > HUK_SUBKEY_MAX_LEN)
70fa0525faSJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
71fa0525faSJens Wiklander if (!const_data && const_data_len)
72fa0525faSJens Wiklander return TEE_ERROR_BAD_PARAMETERS;
73fa0525faSJens Wiklander
74fa0525faSJens Wiklander res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256);
75fa0525faSJens Wiklander if (res)
76fa0525faSJens Wiklander return res;
77fa0525faSJens Wiklander
78fa0525faSJens Wiklander res = tee_otp_get_hw_unique_key(&huk);
79fa0525faSJens Wiklander if (res)
80fa0525faSJens Wiklander goto out;
81fa0525faSJens Wiklander
82c69bc615SJens Wiklander res = crypto_mac_init(ctx, huk.data, sizeof(huk.data));
83fa0525faSJens Wiklander if (res)
84fa0525faSJens Wiklander goto out;
85fa0525faSJens Wiklander
8617888736SJens Wiklander #ifdef CFG_CORE_HUK_SUBKEY_COMPAT
8717888736SJens Wiklander res = huk_compat(ctx, usage);
8817888736SJens Wiklander #else
89fa0525faSJens Wiklander res = mac_usage(ctx, usage);
9017888736SJens Wiklander #endif
91fa0525faSJens Wiklander if (res)
92fa0525faSJens Wiklander goto out;
93fa0525faSJens Wiklander
94fa0525faSJens Wiklander if (const_data) {
95c69bc615SJens Wiklander res = crypto_mac_update(ctx, const_data, const_data_len);
96fa0525faSJens Wiklander if (res)
97fa0525faSJens Wiklander goto out;
98fa0525faSJens Wiklander }
99fa0525faSJens Wiklander
100c69bc615SJens Wiklander res = crypto_mac_final(ctx, subkey, subkey_len);
101fa0525faSJens Wiklander out:
102fa0525faSJens Wiklander if (res)
1033ca4a1caSJerome Forissier memzero_explicit(subkey, subkey_len);
1043ca4a1caSJerome Forissier memzero_explicit(&huk, sizeof(huk));
105c69bc615SJens Wiklander crypto_mac_free_ctx(ctx);
106fa0525faSJens Wiklander return res;
107fa0525faSJens Wiklander }
108*e6e1a209SThomas Bourgoin
109*e6e1a209SThomas Bourgoin TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
110*e6e1a209SThomas Bourgoin const void *const_data, size_t const_data_len,
111*e6e1a209SThomas Bourgoin uint8_t *subkey, size_t subkey_len)
112*e6e1a209SThomas Bourgoin __weak __alias("__huk_subkey_derive");
113