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