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