]>
Commit | Line | Data |
---|---|---|
b9eebfad RG |
1 | /* |
2 | * SEC Descriptor Construction Library | |
3 | * Basic job descriptor construction | |
4 | * | |
5 | * Copyright 2014 Freescale Semiconductor, Inc. | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0+ | |
8 | * | |
9 | */ | |
10 | ||
11 | #include <common.h> | |
0200020b | 12 | #include <fsl_sec.h> |
b9eebfad RG |
13 | #include "desc_constr.h" |
14 | #include "jobdesc.h" | |
34276478 | 15 | #include "rsa_caam.h" |
b9eebfad | 16 | |
f91e65a7 | 17 | #if defined(CONFIG_MX6) || defined(CONFIG_MX7) |
0200020b RC |
18 | /*! |
19 | * Secure memory run command | |
20 | * | |
21 | * @param sec_mem_cmd Secure memory command register | |
22 | * @return cmd_status Secure memory command status register | |
23 | */ | |
24 | uint32_t secmem_set_cmd(uint32_t sec_mem_cmd) | |
25 | { | |
26 | uint32_t temp_reg; | |
27 | ||
f91e65a7 UC |
28 | ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR; |
29 | uint32_t sm_vid = SM_VERSION(sec_in32(&sec->smvid)); | |
30 | uint32_t jr_id = 0; | |
31 | ||
32 | sec_out32(CAAM_SMCJR(sm_vid, jr_id), sec_mem_cmd); | |
0200020b RC |
33 | |
34 | do { | |
f91e65a7 | 35 | temp_reg = sec_in32(CAAM_SMCSJR(sm_vid, jr_id)); |
0200020b RC |
36 | } while (temp_reg & CMD_COMPLETE); |
37 | ||
38 | return temp_reg; | |
39 | } | |
40 | ||
41 | /*! | |
42 | * CAAM page allocation: | |
43 | * Allocates a partition from secure memory, with the id | |
44 | * equal to partion_num. This will de-allocate the page | |
45 | * if it is already allocated. The partition will have | |
46 | * full access permissions. The permissions are set before, | |
47 | * running a job descriptor. A memory page of secure RAM | |
48 | * is allocated for the partition. | |
49 | * | |
50 | * @param page Number of the page to allocate. | |
51 | * @param partition Number of the partition to allocate. | |
52 | * @return 0 on success, ERROR_IN_PAGE_ALLOC otherwise | |
53 | */ | |
54 | int caam_page_alloc(uint8_t page_num, uint8_t partition_num) | |
55 | { | |
56 | uint32_t temp_reg; | |
57 | ||
f91e65a7 UC |
58 | ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR; |
59 | uint32_t sm_vid = SM_VERSION(sec_in32(&sec->smvid)); | |
60 | uint32_t jr_id = 0; | |
61 | ||
0200020b RC |
62 | /* |
63 | * De-Allocate partition_num if already allocated to ARM core | |
64 | */ | |
65 | if (sec_in32(CAAM_SMPO_0) & PARTITION_OWNER(partition_num)) { | |
66 | temp_reg = secmem_set_cmd(PARTITION(partition_num) | | |
67 | CMD_PART_DEALLOC); | |
68 | if (temp_reg & SMCSJR_AERR) { | |
69 | printf("Error: De-allocation status 0x%X\n", temp_reg); | |
70 | return ERROR_IN_PAGE_ALLOC; | |
71 | } | |
72 | } | |
73 | ||
74 | /* set the access rights to allow full access */ | |
f91e65a7 UC |
75 | sec_out32(CAAM_SMAG1JR(sm_vid, jr_id, partition_num), 0xF); |
76 | sec_out32(CAAM_SMAG2JR(sm_vid, jr_id, partition_num), 0xF); | |
77 | sec_out32(CAAM_SMAPJR(sm_vid, jr_id, partition_num), 0xFF); | |
0200020b RC |
78 | |
79 | /* Now need to allocate partition_num of secure RAM. */ | |
80 | /* De-Allocate page_num by starting with a page inquiry command */ | |
81 | temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY); | |
82 | ||
83 | /* if the page is owned, de-allocate it */ | |
84 | if ((temp_reg & SMCSJR_PO) == PAGE_OWNED) { | |
85 | temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_PAGE_DEALLOC); | |
86 | if (temp_reg & SMCSJR_AERR) { | |
87 | printf("Error: Allocation status 0x%X\n", temp_reg); | |
88 | return ERROR_IN_PAGE_ALLOC; | |
89 | } | |
90 | } | |
91 | ||
92 | /* Allocate page_num to partition_num */ | |
93 | temp_reg = secmem_set_cmd(PAGE(page_num) | PARTITION(partition_num) | |
94 | | CMD_PAGE_ALLOC); | |
95 | if (temp_reg & SMCSJR_AERR) { | |
96 | printf("Error: Allocation status 0x%X\n", temp_reg); | |
97 | return ERROR_IN_PAGE_ALLOC; | |
98 | } | |
99 | /* page inquiry command to ensure that the page was allocated */ | |
100 | temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY); | |
101 | ||
102 | /* if the page is not owned => problem */ | |
103 | if ((temp_reg & SMCSJR_PO) != PAGE_OWNED) { | |
104 | printf("Allocation of page %d in partition %d failed 0x%X\n", | |
105 | temp_reg, page_num, partition_num); | |
106 | ||
107 | return ERROR_IN_PAGE_ALLOC; | |
108 | } | |
109 | ||
110 | return 0; | |
111 | } | |
112 | ||
113 | int inline_cnstr_jobdesc_blob_dek(uint32_t *desc, const uint8_t *plain_txt, | |
114 | uint8_t *dek_blob, uint32_t in_sz) | |
115 | { | |
f91e65a7 UC |
116 | ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR; |
117 | uint32_t sm_vid = SM_VERSION(sec_in32(&sec->smvid)); | |
118 | uint32_t jr_id = 0; | |
119 | ||
0200020b RC |
120 | uint32_t ret = 0; |
121 | u32 aad_w1, aad_w2; | |
122 | /* output blob will have 32 bytes key blob in beginning and | |
123 | * 16 byte HMAC identifier at end of data blob */ | |
124 | uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE; | |
125 | /* Setting HDR for blob */ | |
126 | uint8_t wrapped_key_hdr[8] = {HDR_TAG, 0x00, WRP_HDR_SIZE + out_sz, | |
127 | HDR_PAR, HAB_MOD, HAB_ALG, in_sz, HAB_FLG}; | |
128 | ||
129 | /* initialize the blob array */ | |
130 | memset(dek_blob, 0, out_sz + 8); | |
131 | /* Copy the header into the DEK blob buffer */ | |
132 | memcpy(dek_blob, wrapped_key_hdr, sizeof(wrapped_key_hdr)); | |
133 | ||
134 | /* allocating secure memory */ | |
135 | ret = caam_page_alloc(PAGE_1, PARTITION_1); | |
136 | if (ret) | |
137 | return ret; | |
138 | ||
139 | /* Write DEK to secure memory */ | |
140 | memcpy((uint32_t *)SEC_MEM_PAGE1, (uint32_t *)plain_txt, in_sz); | |
141 | ||
142 | unsigned long start = (unsigned long)SEC_MEM_PAGE1 & | |
143 | ~(ARCH_DMA_MINALIGN - 1); | |
144 | unsigned long end = ALIGN(start + 0x1000, ARCH_DMA_MINALIGN); | |
145 | flush_dcache_range(start, end); | |
146 | ||
147 | /* Now configure the access rights of the partition */ | |
f91e65a7 UC |
148 | sec_out32(CAAM_SMAG1JR(sm_vid, jr_id, PARTITION_1), KS_G1); |
149 | sec_out32(CAAM_SMAG2JR(sm_vid, jr_id, PARTITION_1), 0); | |
150 | sec_out32(CAAM_SMAPJR(sm_vid, jr_id, PARTITION_1), PERM); | |
0200020b RC |
151 | |
152 | /* construct aad for AES */ | |
153 | aad_w1 = (in_sz << OP_ALG_ALGSEL_SHIFT) | KEY_AES_SRC | LD_CCM_MODE; | |
154 | aad_w2 = 0x0; | |
155 | ||
156 | init_job_desc(desc, 0); | |
157 | ||
158 | append_cmd(desc, CMD_LOAD | CLASS_2 | KEY_IMM | KEY_ENC | | |
159 | (0x0c << LDST_OFFSET_SHIFT) | 0x08); | |
160 | ||
161 | append_u32(desc, aad_w1); | |
162 | ||
163 | append_u32(desc, aad_w2); | |
164 | ||
165 | append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR); | |
166 | ||
167 | append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR); | |
168 | ||
169 | append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | | |
170 | OP_PCLID_SECMEM); | |
171 | ||
172 | return ret; | |
173 | } | |
174 | #endif | |
c5de15cb | 175 | |
b9eebfad RG |
176 | void inline_cnstr_jobdesc_hash(uint32_t *desc, |
177 | const uint8_t *msg, uint32_t msgsz, uint8_t *digest, | |
178 | u32 alg_type, uint32_t alg_size, int sg_tbl) | |
179 | { | |
180 | /* SHA 256 , output is of length 32 words */ | |
181 | uint32_t storelen = alg_size; | |
182 | u32 options; | |
183 | dma_addr_t dma_addr_in, dma_addr_out; | |
184 | ||
185 | dma_addr_in = virt_to_phys((void *)msg); | |
186 | dma_addr_out = virt_to_phys((void *)digest); | |
187 | ||
188 | init_job_desc(desc, 0); | |
189 | append_operation(desc, OP_TYPE_CLASS2_ALG | | |
190 | OP_ALG_AAI_HASH | OP_ALG_AS_INITFINAL | | |
191 | OP_ALG_ENCRYPT | OP_ALG_ICV_OFF | alg_type); | |
192 | ||
193 | options = LDST_CLASS_2_CCB | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2; | |
194 | if (sg_tbl) | |
195 | options |= FIFOLDST_SGF; | |
196 | if (msgsz > 0xffff) { | |
197 | options |= FIFOLDST_EXT; | |
198 | append_fifo_load(desc, dma_addr_in, 0, options); | |
199 | append_cmd(desc, msgsz); | |
200 | } else { | |
201 | append_fifo_load(desc, dma_addr_in, msgsz, options); | |
202 | } | |
203 | ||
204 | append_store(desc, dma_addr_out, storelen, | |
205 | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT); | |
206 | } | |
c5de15cb RG |
207 | |
208 | void inline_cnstr_jobdesc_blob_encap(uint32_t *desc, uint8_t *key_idnfr, | |
209 | uint8_t *plain_txt, uint8_t *enc_blob, | |
210 | uint32_t in_sz) | |
211 | { | |
212 | dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out; | |
213 | uint32_t key_sz = KEY_IDNFR_SZ_BYTES; | |
214 | /* output blob will have 32 bytes key blob in beginning and | |
215 | * 16 byte HMAC identifier at end of data blob */ | |
216 | uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE; | |
217 | ||
218 | dma_addr_key_idnfr = virt_to_phys((void *)key_idnfr); | |
219 | dma_addr_in = virt_to_phys((void *)plain_txt); | |
220 | dma_addr_out = virt_to_phys((void *)enc_blob); | |
221 | ||
222 | init_job_desc(desc, 0); | |
223 | ||
224 | append_key(desc, dma_addr_key_idnfr, key_sz, CLASS_2); | |
225 | ||
226 | append_seq_in_ptr(desc, dma_addr_in, in_sz, 0); | |
227 | ||
228 | append_seq_out_ptr(desc, dma_addr_out, out_sz, 0); | |
229 | ||
230 | append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); | |
231 | } | |
232 | ||
233 | void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr, | |
234 | uint8_t *enc_blob, uint8_t *plain_txt, | |
235 | uint32_t out_sz) | |
236 | { | |
237 | dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out; | |
238 | uint32_t key_sz = KEY_IDNFR_SZ_BYTES; | |
239 | uint32_t in_sz = out_sz + KEY_BLOB_SIZE + MAC_SIZE; | |
240 | ||
241 | dma_addr_key_idnfr = virt_to_phys((void *)key_idnfr); | |
242 | dma_addr_in = virt_to_phys((void *)enc_blob); | |
243 | dma_addr_out = virt_to_phys((void *)plain_txt); | |
244 | ||
245 | init_job_desc(desc, 0); | |
246 | ||
247 | append_key(desc, dma_addr_key_idnfr, key_sz, CLASS_2); | |
248 | ||
249 | append_seq_in_ptr(desc, dma_addr_in, in_sz, 0); | |
250 | ||
251 | append_seq_out_ptr(desc, dma_addr_out, out_sz, 0); | |
252 | ||
253 | append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB); | |
254 | } | |
255 | ||
256 | /* | |
257 | * Descriptor to instantiate RNG State Handle 0 in normal mode and | |
258 | * load the JDKEK, TDKEK and TDSK registers | |
259 | */ | |
260 | void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc) | |
261 | { | |
262 | u32 *jump_cmd; | |
263 | ||
264 | init_job_desc(desc, 0); | |
265 | ||
266 | /* INIT RNG in non-test mode */ | |
267 | append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | | |
268 | OP_ALG_AS_INIT); | |
269 | ||
270 | /* wait for done */ | |
271 | jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1); | |
272 | set_jump_tgt_here(desc, jump_cmd); | |
273 | ||
274 | /* | |
275 | * load 1 to clear written reg: | |
276 | * resets the done interrrupt and returns the RNG to idle. | |
277 | */ | |
278 | append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW); | |
279 | ||
280 | /* generate secure keys (non-test) */ | |
281 | append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | | |
282 | OP_ALG_RNG4_SK); | |
283 | } | |
34276478 RG |
284 | |
285 | /* Change key size to bytes form bits in calling function*/ | |
286 | void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, | |
287 | struct pk_in_params *pkin, uint8_t *out, | |
288 | uint32_t out_siz) | |
289 | { | |
290 | dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out; | |
291 | ||
292 | dma_addr_e = virt_to_phys((void *)pkin->e); | |
293 | dma_addr_a = virt_to_phys((void *)pkin->a); | |
294 | dma_addr_n = virt_to_phys((void *)pkin->n); | |
295 | dma_addr_out = virt_to_phys((void *)out); | |
296 | ||
297 | init_job_desc(desc, 0); | |
298 | append_key(desc, dma_addr_e, pkin->e_siz, KEY_DEST_PKHA_E | CLASS_1); | |
299 | ||
300 | append_fifo_load(desc, dma_addr_a, | |
301 | pkin->a_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_A); | |
302 | ||
303 | append_fifo_load(desc, dma_addr_n, | |
304 | pkin->n_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_N); | |
305 | ||
306 | append_operation(desc, OP_TYPE_PK | OP_ALG_PK | OP_ALG_PKMODE_MOD_EXPO); | |
307 | ||
308 | append_fifo_store(desc, dma_addr_out, out_siz, | |
309 | LDST_CLASS_1_CCB | FIFOST_TYPE_PKHA_B); | |
310 | } |