xref: /optee_os/core/kernel/huk_subkey.c (revision 178887362ae97acfd0f30653f15ac7e3f18b1e36)
1fa0525faSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2fa0525faSJens Wiklander /*
3fa0525faSJens Wiklander  * Copyright (c) 2019, Linaro Limited
4fa0525faSJens Wiklander  */
5fa0525faSJens Wiklander 
6fa0525faSJens Wiklander #include <crypto/crypto.h>
7fa0525faSJens Wiklander #include <kernel/huk_subkey.h>
8fa0525faSJens Wiklander #include <kernel/tee_common_otp.h>
9*17888736SJens Wiklander #include <tee/tee_fs_key_manager.h>
10fa0525faSJens Wiklander 
11fa0525faSJens Wiklander static TEE_Result mac_usage(void *ctx, uint32_t usage)
12fa0525faSJens Wiklander {
13fa0525faSJens Wiklander 	return crypto_mac_update(ctx, TEE_ALG_HMAC_SHA256,
14fa0525faSJens Wiklander 				 (const void *)&usage, sizeof(usage));
15fa0525faSJens Wiklander }
16fa0525faSJens Wiklander 
17*17888736SJens Wiklander #ifdef CFG_CORE_HUK_SUBKEY_COMPAT
18*17888736SJens Wiklander /*
19*17888736SJens Wiklander  * This gives the result of the default tee_otp_get_die_id()
20*17888736SJens Wiklander  * implementation.
21*17888736SJens Wiklander  */
22*17888736SJens Wiklander static void get_dummy_die_id(uint8_t *buffer, size_t len)
23*17888736SJens Wiklander {
24*17888736SJens Wiklander 	static const char pattern[4] = { 'B', 'E', 'E', 'F' };
25*17888736SJens Wiklander 	size_t i;
26*17888736SJens Wiklander 
27*17888736SJens Wiklander 	for (i = 0; i < len; i++)
28*17888736SJens Wiklander 		buffer[i] = pattern[i % 4];
29*17888736SJens Wiklander }
30*17888736SJens Wiklander 
31*17888736SJens Wiklander /*
32*17888736SJens Wiklander  * This does special treatment for RPMB and SSK key derivations to give
33*17888736SJens Wiklander  * the same result as when huk_subkey_derive() wasn't used.
34*17888736SJens Wiklander  */
35*17888736SJens Wiklander static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage)
36*17888736SJens Wiklander {
37*17888736SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
38*17888736SJens Wiklander 	uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH] = { 0 };
39*17888736SJens Wiklander 	static uint8_t ssk_str[] = "ONLY_FOR_tee_fs_ssk";
40*17888736SJens Wiklander 
41*17888736SJens Wiklander 	switch (usage) {
42*17888736SJens Wiklander 	case HUK_SUBKEY_RPMB:
43*17888736SJens Wiklander 		return TEE_SUCCESS;
44*17888736SJens Wiklander 	case HUK_SUBKEY_SSK:
45*17888736SJens Wiklander 		get_dummy_die_id(chip_id, sizeof(chip_id));
46*17888736SJens Wiklander 		res = crypto_mac_update(ctx, TEE_ALG_HMAC_SHA256,
47*17888736SJens Wiklander 					chip_id, sizeof(chip_id));
48*17888736SJens Wiklander 		if (res)
49*17888736SJens Wiklander 			return res;
50*17888736SJens Wiklander 		return crypto_mac_update(ctx, TEE_ALG_HMAC_SHA256,
51*17888736SJens Wiklander 					 ssk_str, sizeof(ssk_str));
52*17888736SJens Wiklander 	default:
53*17888736SJens Wiklander 		return mac_usage(ctx, usage);
54*17888736SJens Wiklander 	}
55*17888736SJens Wiklander 
56*17888736SJens Wiklander }
57*17888736SJens Wiklander #endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/
58*17888736SJens Wiklander 
59fa0525faSJens Wiklander TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
60fa0525faSJens Wiklander 			     const void *const_data, size_t const_data_len,
61fa0525faSJens Wiklander 			     uint8_t *subkey, size_t subkey_len)
62fa0525faSJens Wiklander {
63fa0525faSJens Wiklander 	void *ctx = NULL;
64fa0525faSJens Wiklander 	struct tee_hw_unique_key huk = { };
65fa0525faSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
66fa0525faSJens Wiklander 
67fa0525faSJens Wiklander 	if (subkey_len > HUK_SUBKEY_MAX_LEN)
68fa0525faSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
69fa0525faSJens Wiklander 	if (!const_data && const_data_len)
70fa0525faSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
71fa0525faSJens Wiklander 
72fa0525faSJens Wiklander 	res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256);
73fa0525faSJens Wiklander 	if (res)
74fa0525faSJens Wiklander 		return res;
75fa0525faSJens Wiklander 
76fa0525faSJens Wiklander 	res = tee_otp_get_hw_unique_key(&huk);
77fa0525faSJens Wiklander 	if (res)
78fa0525faSJens Wiklander 		goto out;
79fa0525faSJens Wiklander 
80fa0525faSJens Wiklander 	res = crypto_mac_init(ctx, TEE_ALG_HMAC_SHA256, huk.data,
81fa0525faSJens Wiklander 			      sizeof(huk.data));
82fa0525faSJens Wiklander 	if (res)
83fa0525faSJens Wiklander 		goto out;
84fa0525faSJens Wiklander 
85*17888736SJens Wiklander #ifdef CFG_CORE_HUK_SUBKEY_COMPAT
86*17888736SJens Wiklander 	res = huk_compat(ctx, usage);
87*17888736SJens Wiklander #else
88fa0525faSJens Wiklander 	res = mac_usage(ctx, usage);
89*17888736SJens Wiklander #endif
90fa0525faSJens Wiklander 	if (res)
91fa0525faSJens Wiklander 		goto out;
92fa0525faSJens Wiklander 
93fa0525faSJens Wiklander 	if (const_data) {
94fa0525faSJens Wiklander 		res = crypto_mac_update(ctx, TEE_ALG_HMAC_SHA256, const_data,
95fa0525faSJens Wiklander 					const_data_len);
96fa0525faSJens Wiklander 		if (res)
97fa0525faSJens Wiklander 			goto out;
98fa0525faSJens Wiklander 	}
99fa0525faSJens Wiklander 
100fa0525faSJens Wiklander 	res = crypto_mac_final(ctx, TEE_ALG_HMAC_SHA256, subkey, subkey_len);
101fa0525faSJens Wiklander out:
102fa0525faSJens Wiklander 	if (res)
103fa0525faSJens Wiklander 		memset(subkey, 0, subkey_len);
104fa0525faSJens Wiklander 	memset(&huk, 0, sizeof(huk));
105fa0525faSJens Wiklander 	crypto_mac_free_ctx(ctx, TEE_ALG_HMAC_SHA256);
106fa0525faSJens Wiklander 	return res;
107fa0525faSJens Wiklander }
108