aboutsummaryrefslogtreecommitdiff
path: root/core/kernel/huk_subkey.c
blob: 7d6e5bf40d3f25c968950174292cc74d08ec43af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2019, Linaro Limited
 */

#include <crypto/crypto.h>
#include <kernel/huk_subkey.h>
#include <kernel/tee_common_otp.h>

static TEE_Result mac_usage(void *ctx, uint32_t usage)
{
	return crypto_mac_update(ctx, TEE_ALG_HMAC_SHA256,
				 (const void *)&usage, sizeof(usage));
}

TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
			     const void *const_data, size_t const_data_len,
			     uint8_t *subkey, size_t subkey_len)
{
	void *ctx = NULL;
	struct tee_hw_unique_key huk = { };
	TEE_Result res = TEE_SUCCESS;

	if (subkey_len > HUK_SUBKEY_MAX_LEN)
		return TEE_ERROR_BAD_PARAMETERS;
	if (!const_data && const_data_len)
		return TEE_ERROR_BAD_PARAMETERS;

	res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256);
	if (res)
		return res;

	res = tee_otp_get_hw_unique_key(&huk);
	if (res)
		goto out;

	res = crypto_mac_init(ctx, TEE_ALG_HMAC_SHA256, huk.data,
			      sizeof(huk.data));
	if (res)
		goto out;

	res = mac_usage(ctx, usage);
	if (res)
		goto out;

	if (const_data) {
		res = crypto_mac_update(ctx, TEE_ALG_HMAC_SHA256, const_data,
					const_data_len);
		if (res)
			goto out;
	}

	res = crypto_mac_final(ctx, TEE_ALG_HMAC_SHA256, subkey, subkey_len);
out:
	if (res)
		memset(subkey, 0, subkey_len);
	memset(&huk, 0, sizeof(huk));
	crypto_mac_free_ctx(ctx, TEE_ALG_HMAC_SHA256);
	return res;
}