Skip to content

Commit da88f66

Browse files
Emantorldts
authored andcommitted
[FIO fromtree] Minimal HUK implementation without full CAAM driver
From pull-request OP-TEE#3160 imx: enable CAAM clocks before accessing registers The CAAM clocks need to be enabled, otherwise access to the CAAM might result in a bus stall. Signed-off-by: Rouven Czerwinski <[email protected]> plat-imx: pack caam structs Add __attribute__((packed)) to the CAAM struct definitions to ensure the compiler does not insert padding into the structures. Signed-off-by: Rouven Czerwinski <[email protected]> plat-imx: register definitions for CAAM Register Definitions in the same style as used by the jobring allocation code, by extending the structure definitions and inserting padding if the registers are undocumented. Signed-off-by: Rouven Czerwinski <[email protected]> imx_caam: implement tee_otp_get_hw_unique_key Minimal implementation for tee_otp_get_hw_unique_key using the Master Key Verification Blob (MKVB) produced by the CAAM. Only the first 16 bytes are copied into the hw unique key structure, since the MKVB is 32 bytes long. Signed-off-by: Rouven Czerwinski <[email protected]> Signed-off-by: Ricardo Salveti <[email protected]>
1 parent a24550c commit da88f66

2 files changed

Lines changed: 226 additions & 1 deletion

File tree

core/arch/arm/plat-imx/drivers/imx_caam.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,151 @@
99
#include <initcall.h>
1010
#include <io.h>
1111
#include <mm/core_memprot.h>
12+
#include <imx.h>
13+
#include <imx-regs.h>
14+
#include <io.h>
15+
#include <kernel/generic_boot.h>
16+
#include <kernel/tee_common_otp.h>
17+
#include <mm/core_memprot.h>
18+
#include <platform_config.h>
19+
#include <stdint.h>
20+
#include <tee/cache.h>
1221

1322
#include "imx_caam.h"
1423

24+
static uint8_t stored_key[MKVB_SIZE];
25+
static bool mkvb_retrieved;
26+
27+
static void caam_enable_clocks(void)
28+
{
29+
vaddr_t ccm_base = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC);
30+
31+
io_setbits32(ccm_base + CCM_CCGR0,
32+
CCM_CCGR0_CAAM_WRAPPER_IPG |
33+
CCM_CCGR0_CAAM_WRAPPER_ACLK |
34+
CCM_CCGR0_CAAM_SECURE_MEM);
35+
36+
if (soc_is_imx6dqp() || soc_is_imx6sdl() || soc_is_imx6dq())
37+
io_setbits32(ccm_base + CCM_CCGR6,
38+
CCM_CCGR6_EMI_SLOW);
39+
}
40+
41+
static TEE_Result imx_caam_reset_jr(struct imx_caam_ctrl *ctrl)
42+
{
43+
uint32_t reg_val = 0;
44+
uint32_t timeout = 1000;
45+
46+
io_write32((vaddr_t)&ctrl->jrcfg[MKVB_JR].jrcr, 1);
47+
do {
48+
reg_val = io_read32((vaddr_t)&ctrl->jrcfg[MKVB_JR].jrintr);
49+
reg_val &= 0xc;
50+
} while ((reg_val == 0x4) && --timeout);
51+
52+
if (!timeout)
53+
return TEE_ERROR_SECURITY;
54+
55+
io_write32((vaddr_t)&ctrl->jrcfg[MKVB_JR].jrcr, 1);
56+
do {
57+
reg_val = io_read32((vaddr_t)&ctrl->jrcfg[MKVB_JR].jrintr);
58+
reg_val &= 0xc;
59+
} while ((reg_val & 0x1) && --timeout);
60+
61+
if (!timeout)
62+
return TEE_ERROR_SECURITY;
63+
64+
return TEE_SUCCESS;
65+
}
66+
67+
static TEE_Result mkvb_init_jr(struct imx_mkvb *mkvb)
68+
{
69+
struct imx_caam_ctrl *ctrl = mkvb->ctrl;
70+
TEE_Result ret = TEE_ERROR_SECURITY;
71+
72+
ret = imx_caam_reset_jr(ctrl);
73+
if (ret)
74+
return ret;
75+
76+
mkvb->njobs = 4;
77+
io_write32((vaddr_t)&ctrl->jrstartr, MKVB_JR1_START);
78+
io_write32((vaddr_t)&ctrl->jrcfg[MKVB_JR].irbar_ls,
79+
virt_to_phys(&mkvb->jr.inring));
80+
io_write32((vaddr_t)&ctrl->jrcfg[MKVB_JR].irsr, mkvb->njobs);
81+
io_write32((vaddr_t)&ctrl->jrcfg[MKVB_JR].orbar_ls,
82+
virt_to_phys(&mkvb->jr.outring));
83+
io_write32((vaddr_t)&ctrl->jrcfg[MKVB_JR].orsr, mkvb->njobs);
84+
85+
return TEE_SUCCESS;
86+
}
87+
88+
static TEE_Result caam_get_mkvb(uint8_t *dest)
89+
{
90+
struct imx_mkvb mkvb = { 0 };
91+
TEE_Result ret = TEE_ERROR_SECURITY;
92+
paddr_t desc_paddr = 0;
93+
int counter = 0;
94+
95+
mkvb.ctrl = (struct imx_caam_ctrl *)
96+
core_mmu_get_va(CAAM_BASE, MEM_AREA_IO_SEC);
97+
98+
ret = mkvb_init_jr(&mkvb);
99+
if (ret)
100+
goto out;
101+
102+
mkvb.descriptor[0] = MKVB_DESC_HEADER;
103+
mkvb.descriptor[1] = MKVB_DESC_SEQ_OUT;
104+
mkvb.descriptor[2] = virt_to_phys(&mkvb.outbuf);
105+
cache_operation(TEE_CACHEFLUSH, &mkvb.outbuf, MKVB_SIZE);
106+
mkvb.descriptor[3] = MKVB_DESC_BLOB;
107+
cache_operation(TEE_CACHEFLUSH, &mkvb.descriptor,
108+
sizeof(mkvb.descriptor));
109+
110+
desc_paddr = virt_to_phys(&mkvb.descriptor);
111+
memcpy(&mkvb.jr.inring, &desc_paddr, sizeof(desc_paddr));
112+
cache_operation(TEE_CACHEFLUSH, &mkvb.jr,
113+
sizeof(mkvb.jr.inring[0]));
114+
115+
/* Tell CAAM that one job is available */
116+
io_write32((vaddr_t)&mkvb.ctrl->jrcfg[MKVB_JR].irjar, 1);
117+
118+
/* Busy loop until job is completed */
119+
while (io_read32((vaddr_t)&mkvb.ctrl->jrcfg[MKVB_JR].orsfr) != 1) {
120+
counter++;
121+
if (counter > 10000) {
122+
ret = TEE_ERROR_SECURITY;
123+
goto out;
124+
}
125+
}
126+
127+
cache_operation(TEE_CACHEINVALIDATE, &mkvb.jr, sizeof(mkvb.jr));
128+
cache_operation(TEE_CACHEINVALIDATE, &mkvb.outbuf, MKVB_SIZE);
129+
DHEXDUMP(&mkvb.outbuf, MKVB_SIZE);
130+
131+
if (mkvb.jr.outring[0].status != 0) {
132+
ret = TEE_ERROR_SECURITY;
133+
goto out;
134+
}
135+
136+
memcpy(dest, &mkvb.outbuf, MKVB_SIZE);
137+
ret = TEE_SUCCESS;
138+
out:
139+
io_write32((vaddr_t)&mkvb.ctrl->scfgr, PRIBLOB_11);
140+
return ret;
141+
}
142+
143+
TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
144+
{
145+
int ret = TEE_ERROR_SECURITY;
146+
147+
if (!mkvb_retrieved) {
148+
ret = caam_get_mkvb(stored_key);
149+
if (ret)
150+
return ret;
151+
mkvb_retrieved = true;
152+
}
153+
memcpy(&hwkey->data, &stored_key, sizeof(hwkey->data));
154+
return TEE_SUCCESS;
155+
}
156+
15157
register_phys_mem_pgdir(MEM_AREA_IO_SEC, CAAM_BASE, CORE_MMU_PGDIR_SIZE);
16158

17159
static TEE_Result init_caam(void)
@@ -25,6 +167,7 @@ static TEE_Result init_caam(void)
25167
if (!caam)
26168
return TEE_ERROR_GENERIC;
27169

170+
caam_enable_clocks();
28171
/*
29172
* Set job-ring ownership to non-secure by default.
30173
* A Linux kernel that runs after OP-TEE will run in normal-world

core/arch/arm/plat-imx/drivers/imx_caam.h

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,109 @@
99
#ifndef __IMX_CAAM_H__
1010
#define __IMX_CAAM_H__
1111

12+
#include <compiler.h>
1213
#include <imx-regs.h>
1314
#include <stdint.h>
15+
#include <types_ext.h>
1416

1517
struct imx_caam_job_ring {
1618
uint32_t jrmidr_ms;
1719
uint32_t jrmidr_ls;
18-
};
20+
} __packed;
1921

2022
#define CAAM_NUM_JOB_RINGS 4
2123

2224
/* CAAM ownersip definition bits */
2325
#define JROWN_NS BIT(3)
2426
#define JROWN_MID 0x01
2527

28+
/* i.MX6 CAAM clocks bits */
29+
#define CCM_CCGR0 0x0068
30+
#define CCM_CCGR6 0x0080
31+
32+
#define CCM_CCGR0_CAAM_WRAPPER_IPG SHIFT_U32(3, 12)
33+
#define CCM_CCGR0_CAAM_SECURE_MEM SHIFT_U32(3, 8)
34+
#define CCM_CCGR0_CAAM_WRAPPER_ACLK SHIFT_U32(3, 10)
35+
#define CCM_CCGR6_EMI_SLOW SHIFT_U32(3, 10)
36+
37+
/* Descriptor and MKVB Definitions */
38+
#define MKVB_SIZE 32
39+
#define MKVB_DESC_SEQ_OUT 0xf8000020
40+
#define MKVB_DESC_HEADER 0xb0800004
41+
#define MKVB_DESC_BLOB 0x870d0002
42+
43+
/* PRIBLOB Bits */
44+
#define PRIBLOB_11 3
45+
46+
/* JR Bits */
47+
#define MKVB_JR 1
48+
#define MKVB_JR1_START 2
49+
50+
/* jr configuration registers */
51+
struct imx_caam_jr_ctrl {
52+
uint32_t irbar;
53+
uint32_t irbar_ls;
54+
uint8_t padding[4];
55+
uint32_t irsr;
56+
uint8_t padding2[4];
57+
uint32_t irsar;
58+
uint8_t padding3[4];
59+
uint32_t irjar;
60+
uint32_t orbar;
61+
uint32_t orbar_ls;
62+
uint8_t padding4[4];
63+
uint32_t orsr;
64+
uint8_t padding5[4];
65+
uint32_t orjrr;
66+
uint8_t padding6[4];
67+
uint32_t orsfr;
68+
uint8_t padding7[4];
69+
uint32_t jrstar;
70+
uint8_t padding8[4];
71+
uint32_t jrintr;
72+
uint32_t jrcfgr_ms;
73+
uint32_t jrcfgr_ls;
74+
uint8_t padding9[4];
75+
uint32_t irrir;
76+
uint8_t padding10[4];
77+
uint32_t orwir;
78+
uint8_t padding11[4];
79+
uint32_t jrcr;
80+
uint8_t padding12[1688];
81+
uint32_t jraav;
82+
uint8_t padding13[2292];
83+
} __packed;
84+
2685
/* A basic sub-set of the CAAM */
2786
struct imx_caam_ctrl {
2887
uint32_t res0;
2988
uint32_t mcfgr;
3089
uint32_t res1;
3190
uint32_t scfgr;
3291
struct imx_caam_job_ring jr[CAAM_NUM_JOB_RINGS];
92+
uint8_t padding[36];
93+
uint32_t debugctl;
94+
uint32_t jrstartr;
95+
uint8_t padding2[4004];
96+
struct imx_caam_jr_ctrl jrcfg[CAAM_NUM_JOB_RINGS];
97+
} __packed;
98+
99+
#define MKVB_CL_SIZE 64
100+
101+
struct imx_mkvb {
102+
struct {
103+
struct {
104+
uint32_t desc;
105+
} inring[8];
106+
struct {
107+
uint32_t desc;
108+
uint32_t status;
109+
} __packed outring[4];
110+
} __packed __aligned(MKVB_CL_SIZE) jr;
111+
uint32_t descriptor[16] __aligned(MKVB_CL_SIZE);
112+
char outbuf[MKVB_CL_SIZE] __aligned(MKVB_CL_SIZE);
113+
size_t njobs;
114+
struct imx_caam_ctrl *ctrl;
33115
};
34116

35117
#endif /* __IMX_CAAM_H__ */

0 commit comments

Comments
 (0)