1fc716968SThomas Perrot // SPDX-License-Identifier: BSD-2-Clause
2fc716968SThomas Perrot /*
3fc716968SThomas Perrot * Copyright (c) 2023, Microchip
4fc716968SThomas Perrot */
5fc716968SThomas Perrot
6fc716968SThomas Perrot #include <drivers/nvmem.h>
7fc716968SThomas Perrot #include <io.h>
8fc716968SThomas Perrot #include <kernel/dt.h>
9fc716968SThomas Perrot #include <kernel/huk_subkey.h>
10fc716968SThomas Perrot #include <kernel/tee_common_otp.h>
11*c216899eSThomas Perrot #include <libfdt.h>
12fc716968SThomas Perrot #include <malloc.h>
13fc716968SThomas Perrot #include <tee_api_defines.h>
14fc716968SThomas Perrot #include <tee_api_types.h>
15*c216899eSThomas Perrot #include <trace.h>
16fc716968SThomas Perrot #include <types_ext.h>
17fc716968SThomas Perrot
18*c216899eSThomas Perrot static uint8_t *huk;
19fc716968SThomas Perrot
tee_otp_get_hw_unique_key(struct tee_hw_unique_key * hwkey)20fc716968SThomas Perrot TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
21fc716968SThomas Perrot {
22*c216899eSThomas Perrot if (!huk) {
23*c216899eSThomas Perrot EMSG("no HUK");
24*c216899eSThomas Perrot return TEE_ERROR_GENERIC;
25fc716968SThomas Perrot }
26fc716968SThomas Perrot
27fc716968SThomas Perrot memcpy(hwkey->data, huk, HW_UNIQUE_KEY_LENGTH);
28fc716968SThomas Perrot
29*c216899eSThomas Perrot return TEE_SUCCESS;
30fc716968SThomas Perrot }
31fc716968SThomas Perrot
nvmem_huk_probe(const void * fdt,int node,const void * compat_data __unused)32fc716968SThomas Perrot static TEE_Result nvmem_huk_probe(const void *fdt, int node,
33fc716968SThomas Perrot const void *compat_data __unused)
34fc716968SThomas Perrot {
35*c216899eSThomas Perrot TEE_Result res = TEE_ERROR_GENERIC;
36*c216899eSThomas Perrot struct nvmem_cell *cell = NULL;
37*c216899eSThomas Perrot uint8_t *data = NULL;
38*c216899eSThomas Perrot
39*c216899eSThomas Perrot res = nvmem_get_cell_by_name(fdt, node, "hw_unique_key", &cell);
40*c216899eSThomas Perrot if (res)
41*c216899eSThomas Perrot return res;
42*c216899eSThomas Perrot
43*c216899eSThomas Perrot if (cell->len < HW_UNIQUE_KEY_LENGTH) {
44*c216899eSThomas Perrot EMSG("cell %s is too small", fdt_get_name(fdt, node, NULL));
45*c216899eSThomas Perrot nvmem_put_cell(cell);
46*c216899eSThomas Perrot return TEE_ERROR_GENERIC;
47*c216899eSThomas Perrot }
48*c216899eSThomas Perrot
49*c216899eSThomas Perrot if (cell->len > HW_UNIQUE_KEY_LENGTH)
50*c216899eSThomas Perrot IMSG("nvmem_huk: HUK truncated from %zu to %u bytes",
51*c216899eSThomas Perrot cell->len, HW_UNIQUE_KEY_LENGTH);
52*c216899eSThomas Perrot
53*c216899eSThomas Perrot res = nvmem_cell_malloc_and_read(cell, &data);
54*c216899eSThomas Perrot if (!res)
55*c216899eSThomas Perrot huk = data;
56*c216899eSThomas Perrot
57*c216899eSThomas Perrot nvmem_put_cell(cell);
58*c216899eSThomas Perrot
59*c216899eSThomas Perrot return res;
60fc716968SThomas Perrot }
61fc716968SThomas Perrot
62fc716968SThomas Perrot static const struct dt_device_match nvmem_huk_match_table[] = {
63fc716968SThomas Perrot { .compatible = "optee,nvmem-huk" },
64fc716968SThomas Perrot { }
65fc716968SThomas Perrot };
66fc716968SThomas Perrot
67fc716968SThomas Perrot DEFINE_DT_DRIVER(nvmem_huk_dt_driver) = {
68fc716968SThomas Perrot .name = "nvmem_huk",
69fc716968SThomas Perrot .type = DT_DRIVER_NVMEM,
70fc716968SThomas Perrot .match_table = nvmem_huk_match_table,
71fc716968SThomas Perrot .probe = nvmem_huk_probe,
72fc716968SThomas Perrot };
73