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