imx6: Added DEK blob generator command
Freescale's SEC block has built-in Data Encryption
Key(DEK) Blob Protocol which provides a method for
protecting a DEK for non-secure memory storage.
SEC block protects data in a data structure called
a Secret Key Blob, which provides both confidentiality
and integrity protection.
Every time the blob encapsulation is executed,
a AES-256 key is randomly generated to encrypt the DEK.
This key is encrypted with the OTP Secret key
from SoC. The resulting blob consists of the encrypted
AES-256 key, the encrypted DEK, and a 16-bit MAC.
During decapsulation, the reverse process is performed
to get back the original DEK. A caveat to the blob
decapsulation process,  is that the DEK is decrypted
in secure-memory and can only be read by FSL SEC HW.
The DEK is used to decrypt data during encrypted boot.
Commands added
--------------
  dek_blob - encapsulating DEK as a cryptgraphic blob
Commands Syntax
---------------
  dek_blob src dst len
    Encapsulate and create blob of a len-bits DEK at
    address src and store the result at address dst.
Signed-off-by: Raul Cardenas <Ulises.Cardenas@freescale.com>
Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
Signed-off-by: Ulises Cardenas <ulises.cardenas@freescale.com>
Signed-off-by: Ulises Cardenas-B45798 <Ulises.Cardenas@freescale.com>
			
			
This commit is contained in:
		
							parent
							
								
									b5cd10b911
								
							
						
					
					
						commit
						0200020bc2
					
				|  | @ -24,6 +24,7 @@ obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o | ||||||
| endif | endif | ||||||
| obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o | obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o | ||||||
| obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o | obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o | ||||||
|  | obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o | ||||||
| 
 | 
 | ||||||
| quiet_cmd_cpp_cfg = CFGS    $@ | quiet_cmd_cpp_cfg = CFGS    $@ | ||||||
|       cmd_cpp_cfg = $(CPP) $(cpp_flags) -x c -o $@ $< |       cmd_cpp_cfg = $(CPP) $(cpp_flags) -x c -o $@ $< | ||||||
|  |  | ||||||
|  | @ -0,0 +1,91 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright 2008-2015 Freescale Semiconductor, Inc. | ||||||
|  |  * | ||||||
|  |  * SPDX-License-Identifier: GPL-2.0+ | ||||||
|  |  * | ||||||
|  |  * Command for encapsulating DEK blob | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <command.h> | ||||||
|  | #include <environment.h> | ||||||
|  | #include <malloc.h> | ||||||
|  | #include <asm/byteorder.h> | ||||||
|  | #include <linux/compiler.h> | ||||||
|  | #include <fsl_sec.h> | ||||||
|  | #include <asm/arch/clock.h> | ||||||
|  | 
 | ||||||
|  | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  | * blob_dek() - Encapsulate the DEK as a blob using CAM's Key | ||||||
|  | * @src: - Address of data to be encapsulated | ||||||
|  | * @dst: - Desination address of encapsulated data | ||||||
|  | * @len: - Size of data to be encapsulated | ||||||
|  | * | ||||||
|  | * Returns zero on success,and negative on error. | ||||||
|  | */ | ||||||
|  | static int blob_encap_dek(const u8 *src, u8 *dst, u32 len) | ||||||
|  | { | ||||||
|  | 	int ret = 0; | ||||||
|  | 	u32 jr_size = 4; | ||||||
|  | 
 | ||||||
|  | 	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR + 0x102c); | ||||||
|  | 	if (out_jr_size != jr_size) { | ||||||
|  | 		hab_caam_clock_enable(1); | ||||||
|  | 		sec_init(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!((len == 128) | (len == 192) | (len == 256))) { | ||||||
|  | 		debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	len /= 8; | ||||||
|  | 	ret = blob_dek(src, dst, len); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * do_dek_blob() - Handle the "dek_blob" command-line command | ||||||
|  |  * @cmdtp:  Command data struct pointer | ||||||
|  |  * @flag:   Command flag | ||||||
|  |  * @argc:   Command-line argument count | ||||||
|  |  * @argv:   Array of command-line arguments | ||||||
|  |  * | ||||||
|  |  * Returns zero on success, CMD_RET_USAGE in case of misuse and negative | ||||||
|  |  * on error. | ||||||
|  |  */ | ||||||
|  | static int do_dek_blob(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) | ||||||
|  | { | ||||||
|  | 	uint32_t src_addr, dst_addr, len; | ||||||
|  | 	uint8_t *src_ptr, *dst_ptr; | ||||||
|  | 	int ret = 0; | ||||||
|  | 
 | ||||||
|  | 	if (argc != 4) | ||||||
|  | 		return CMD_RET_USAGE; | ||||||
|  | 
 | ||||||
|  | 	src_addr = simple_strtoul(argv[1], NULL, 16); | ||||||
|  | 	dst_addr = simple_strtoul(argv[2], NULL, 16); | ||||||
|  | 	len = simple_strtoul(argv[3], NULL, 10); | ||||||
|  | 
 | ||||||
|  | 	src_ptr = map_sysmem(src_addr, len/8); | ||||||
|  | 	dst_ptr = map_sysmem(dst_addr, BLOB_SIZE(len/8)); | ||||||
|  | 
 | ||||||
|  | 	ret = blob_encap_dek(src_ptr, dst_ptr, len); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /***************************************************/ | ||||||
|  | static char dek_blob_help_text[] = | ||||||
|  | 	"src dst len            - Encapsulate and create blob of data\n" | ||||||
|  | 	"                         $len bits long at address $src and\n" | ||||||
|  | 	"                         store the result at address $dst.\n"; | ||||||
|  | 
 | ||||||
|  | U_BOOT_CMD( | ||||||
|  | 	dek_blob, 4, 1, do_dek_blob, | ||||||
|  | 	"Data Encryption Key blob encapsulation", | ||||||
|  | 	dek_blob_help_text | ||||||
|  | ); | ||||||
|  | @ -176,3 +176,20 @@ ulong get_tbclk(void) | ||||||
| { | { | ||||||
| 	return gpt_get_clk(); | 	return gpt_get_clk(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * This function is intended for SHORT delays only. | ||||||
|  |  * It will overflow at around 10 seconds @ 400MHz, | ||||||
|  |  * or 20 seconds @ 200MHz. | ||||||
|  |  */ | ||||||
|  | unsigned long usec2ticks(unsigned long usec) | ||||||
|  | { | ||||||
|  | 	ulong ticks; | ||||||
|  | 
 | ||||||
|  | 	if (usec < 1000) | ||||||
|  | 		ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000; | ||||||
|  | 	else | ||||||
|  | 		ticks = ((usec / 10) * (get_tbclk() / 100000)); | ||||||
|  | 
 | ||||||
|  | 	return ticks; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -215,6 +215,10 @@ | ||||||
| #define AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000) | #define AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000) | ||||||
| #define CAAM_BASE_ADDR              (ATZ2_BASE_ADDR) | #define CAAM_BASE_ADDR              (ATZ2_BASE_ADDR) | ||||||
| #define ARM_BASE_ADDR		    (ATZ2_BASE_ADDR + 0x40000) | #define ARM_BASE_ADDR		    (ATZ2_BASE_ADDR + 0x40000) | ||||||
|  | 
 | ||||||
|  | #define CONFIG_SYS_FSL_SEC_ADDR     CAAM_BASE_ADDR | ||||||
|  | #define CONFIG_SYS_FSL_JR0_ADDR     (CAAM_BASE_ADDR + 0x1000) | ||||||
|  | 
 | ||||||
| #define USB_PL301_BASE_ADDR         (AIPS2_OFF_BASE_ADDR + 0x0000) | #define USB_PL301_BASE_ADDR         (AIPS2_OFF_BASE_ADDR + 0x0000) | ||||||
| #define USB_BASE_ADDR               (AIPS2_OFF_BASE_ADDR + 0x4000) | #define USB_BASE_ADDR               (AIPS2_OFF_BASE_ADDR + 0x4000) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -46,3 +46,51 @@ cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx | ||||||
| 
 | 
 | ||||||
| NOTE: U-Boot_CSF.bin needs to be padded to the value specified in | NOTE: U-Boot_CSF.bin needs to be padded to the value specified in | ||||||
| the imximage.cfg file. | the imximage.cfg file. | ||||||
|  | 
 | ||||||
|  | Setup U-Boot Image for Encrypted Boot | ||||||
|  | ------------------------------------- | ||||||
|  | An authenticated U-Boot image is used as starting point for | ||||||
|  | Encrypted Boot. The image is encrypted by Freescale's Code | ||||||
|  | Signing Tool (CST). The CST replaces only the image data of | ||||||
|  | u-boot.imx with the encrypted data. The Initial Vector Table, | ||||||
|  | DCD, and Boot data, remains in plaintext. | ||||||
|  | 
 | ||||||
|  | The image data is encrypted with a Encryption Key (DEK). | ||||||
|  | Therefore, this key is needed to decrypt the data during the | ||||||
|  | booting process. The DEK is protected by wrapping it in a Blob, | ||||||
|  | which needs to be appended to the U-Boot image and specified in | ||||||
|  | the CSF file. | ||||||
|  | 
 | ||||||
|  | The DEK blob is generated by an authenticated U-Boot image with | ||||||
|  | the dek_blob cmd enabled. The image used for DEK blob generation | ||||||
|  | needs to have the following configurations enabled: | ||||||
|  | 
 | ||||||
|  | CONFIG_SECURE_BOOT | ||||||
|  | CONFIG_SYS_FSL_SEC_COMPAT    4 /* HAB version */ | ||||||
|  | CONFIG_FSL_CAAM | ||||||
|  | CONFIG_CMD_DEKBLOB | ||||||
|  | 
 | ||||||
|  | Note: The encrypted boot feature is only supported by HABv4 or | ||||||
|  | greater. | ||||||
|  | 
 | ||||||
|  | The dek_blob command then can be used to generate the DEK blob of | ||||||
|  | a DEK previously loaded in memory. The command is used as follows: | ||||||
|  | 
 | ||||||
|  | dek_blob <DEK address> <Output Address> <Key Size in Bits> | ||||||
|  | example: dek_blob 0x10800000 0x10801000 192 | ||||||
|  | 
 | ||||||
|  | The resulting DEK blob then is used to construct the encrypted | ||||||
|  | U-Boot image. Note that the blob needs to be transferred back | ||||||
|  | to the host.Then the following commands are used to construct | ||||||
|  | the final image. | ||||||
|  | 
 | ||||||
|  | objcopy -I binary -O binary --pad-to 0x2000 --gap-fill=0x00 \ | ||||||
|  |     U-Boot_CSF.bin U-Boot_CSF_pad.bin | ||||||
|  | cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx | ||||||
|  | objcopy -I binary -O binary --pad-to <blob_dst> --gap-fill=0x00 \ | ||||||
|  |     u-boot-signed.imx u-boot-signed-pad.bin | ||||||
|  | cat u-boot-signed-pad.imx DEK_blob.bin > u-boot-encrypted.imx | ||||||
|  | 
 | ||||||
|  |     NOTE: u-boot-signed.bin needs to be padded to the value | ||||||
|  |     equivalent to the address in which the DEK blob is specified | ||||||
|  |     in the CSF. | ||||||
|  |  | ||||||
|  | @ -8,5 +8,5 @@ | ||||||
| 
 | 
 | ||||||
| obj-y += sec.o | obj-y += sec.o | ||||||
| obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o | obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o | ||||||
| obj-$(CONFIG_CMD_BLOB) += fsl_blob.o | obj-$(CONFIG_CMD_BLOB)$(CONFIG_CMD_DEKBLOB) += fsl_blob.o | ||||||
| obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o | obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o | ||||||
|  |  | ||||||
|  | @ -12,11 +12,18 @@ | ||||||
| #ifndef DESC_H | #ifndef DESC_H | ||||||
| #define DESC_H | #define DESC_H | ||||||
| 
 | 
 | ||||||
|  | #define KEY_BLOB_SIZE		32 | ||||||
|  | #define MAC_SIZE			16 | ||||||
|  | 
 | ||||||
| /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */ | /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */ | ||||||
| #define MAX_CAAM_DESCSIZE	64 | #define MAX_CAAM_DESCSIZE	64 | ||||||
| 
 | 
 | ||||||
|  | /* Size of DEK Blob  descriptor, inclusive of header */ | ||||||
|  | #define DEK_BLOB_DESCSIZE	9 | ||||||
|  | 
 | ||||||
| /* Block size of any entity covered/uncovered with a KEK/TKEK */ | /* Block size of any entity covered/uncovered with a KEK/TKEK */ | ||||||
| #define KEK_BLOCKSIZE		16 | #define KEK_BLOCKSIZE		16 | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Supported descriptor command types as they show up |  * Supported descriptor command types as they show up | ||||||
|  * inside a descriptor command word. |  * inside a descriptor command word. | ||||||
|  | @ -272,6 +279,13 @@ | ||||||
| #define LDLEN_SET_OFIFO_OFFSET_SHIFT	0 | #define LDLEN_SET_OFIFO_OFFSET_SHIFT	0 | ||||||
| #define LDLEN_SET_OFIFO_OFFSET_MASK	(3 << LDLEN_SET_OFIFO_OFFSET_SHIFT) | #define LDLEN_SET_OFIFO_OFFSET_MASK	(3 << LDLEN_SET_OFIFO_OFFSET_SHIFT) | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * AAD Definitions | ||||||
|  |  */ | ||||||
|  | #define AES_KEY_SHIFT		8 | ||||||
|  | #define LD_CCM_MODE		0x66 | ||||||
|  | #define KEY_AES_SRC		(0x55 << AES_KEY_SHIFT) | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE |  * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE | ||||||
|  * Command Constructs |  * Command Constructs | ||||||
|  | @ -418,6 +432,7 @@ | ||||||
| #define OP_PCLID_MASK		(0xff << 16) | #define OP_PCLID_MASK		(0xff << 16) | ||||||
| 
 | 
 | ||||||
| /* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */ | /* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */ | ||||||
|  | #define OP_PCLID_SECMEM		0x08 | ||||||
| #define OP_PCLID_BLOB		(0x0d << OP_PCLID_SHIFT) | #define OP_PCLID_BLOB		(0x0d << OP_PCLID_SHIFT) | ||||||
| #define OP_PCLID_SECRETKEY	(0x11 << OP_PCLID_SHIFT) | #define OP_PCLID_SECRETKEY	(0x11 << OP_PCLID_SHIFT) | ||||||
| #define OP_PCLID_PUBLICKEYPAIR	(0x14 << OP_PCLID_SHIFT) | #define OP_PCLID_PUBLICKEYPAIR	(0x14 << OP_PCLID_SHIFT) | ||||||
|  |  | ||||||
|  | @ -7,6 +7,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
|  | #include <fsl_sec.h> | ||||||
|  | #include <asm-generic/errno.h> | ||||||
| #include "jobdesc.h" | #include "jobdesc.h" | ||||||
| #include "desc.h" | #include "desc.h" | ||||||
| #include "jr.h" | #include "jr.h" | ||||||
|  | @ -59,3 +61,53 @@ int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len) | ||||||
| 	free(desc); | 	free(desc); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_CMD_DEKBLOB | ||||||
|  | int blob_dek(const u8 *src, u8 *dst, u8 len) | ||||||
|  | { | ||||||
|  | 	int ret, size, i = 0; | ||||||
|  | 	u32 *desc; | ||||||
|  | 
 | ||||||
|  | 	int out_sz =  WRP_HDR_SIZE + len + KEY_BLOB_SIZE + MAC_SIZE; | ||||||
|  | 
 | ||||||
|  | 	puts("\nEncapsulating provided DEK to form blob\n"); | ||||||
|  | 	desc = memalign(ARCH_DMA_MINALIGN, | ||||||
|  | 			sizeof(uint32_t) * DEK_BLOB_DESCSIZE); | ||||||
|  | 	if (!desc) { | ||||||
|  | 		debug("Not enough memory for descriptor allocation\n"); | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ret = inline_cnstr_jobdesc_blob_dek(desc, src, dst, len); | ||||||
|  | 	if (ret) { | ||||||
|  | 		debug("Error in Job Descriptor Construction:  %d\n", ret); | ||||||
|  | 	} else { | ||||||
|  | 		size = roundup(sizeof(uint32_t) * DEK_BLOB_DESCSIZE, | ||||||
|  | 			      ARCH_DMA_MINALIGN); | ||||||
|  | 		flush_dcache_range((unsigned long)desc, | ||||||
|  | 				   (unsigned long)desc + size); | ||||||
|  | 		size = roundup(sizeof(uint8_t) * out_sz, ARCH_DMA_MINALIGN); | ||||||
|  | 		flush_dcache_range((unsigned long)dst, | ||||||
|  | 				   (unsigned long)dst + size); | ||||||
|  | 
 | ||||||
|  | 		ret = run_descriptor_jr(desc); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (ret) { | ||||||
|  | 		debug("Error in Encapsulation %d\n", ret); | ||||||
|  | 	   goto err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	size = roundup(out_sz, ARCH_DMA_MINALIGN); | ||||||
|  | 	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst+size); | ||||||
|  | 
 | ||||||
|  | 	puts("DEK Blob\n"); | ||||||
|  | 	for (i = 0; i < out_sz; i++) | ||||||
|  | 		printf("%02X", ((uint8_t *)dst)[i]); | ||||||
|  | 	printf("\n"); | ||||||
|  | 
 | ||||||
|  | err: | ||||||
|  | 	free(desc); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | @ -9,12 +9,157 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
|  | #include <fsl_sec.h> | ||||||
| #include "desc_constr.h" | #include "desc_constr.h" | ||||||
| #include "jobdesc.h" | #include "jobdesc.h" | ||||||
| #include "rsa_caam.h" | #include "rsa_caam.h" | ||||||
| 
 | 
 | ||||||
| #define KEY_BLOB_SIZE			32 | #ifdef CONFIG_MX6 | ||||||
| #define MAC_SIZE			16 | /*!
 | ||||||
|  |  * Secure memory run command | ||||||
|  |  * | ||||||
|  |  * @param   sec_mem_cmd  Secure memory command register | ||||||
|  |  * @return  cmd_status  Secure memory command status register | ||||||
|  |  */ | ||||||
|  | uint32_t secmem_set_cmd(uint32_t sec_mem_cmd) | ||||||
|  | { | ||||||
|  | 	uint32_t temp_reg; | ||||||
|  | 
 | ||||||
|  | 	sec_out32(CAAM_SMCJR0, sec_mem_cmd); | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		temp_reg = sec_in32(CAAM_SMCSJR0); | ||||||
|  | 	} while (temp_reg & CMD_COMPLETE); | ||||||
|  | 
 | ||||||
|  | 	return temp_reg; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*!
 | ||||||
|  |  * CAAM page allocation: | ||||||
|  |  * Allocates a partition from secure memory, with the id | ||||||
|  |  * equal to partion_num. This will de-allocate the page | ||||||
|  |  * if it is already allocated. The partition will have | ||||||
|  |  * full access permissions. The permissions are set before, | ||||||
|  |  * running a job descriptor. A memory page of secure RAM | ||||||
|  |  * is allocated for the partition. | ||||||
|  |  * | ||||||
|  |  * @param   page  Number of the page to allocate. | ||||||
|  |  * @param   partition  Number of the partition to allocate. | ||||||
|  |  * @return  0 on success, ERROR_IN_PAGE_ALLOC otherwise | ||||||
|  |  */ | ||||||
|  | int caam_page_alloc(uint8_t page_num, uint8_t partition_num) | ||||||
|  | { | ||||||
|  | 	uint32_t temp_reg; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * De-Allocate partition_num if already allocated to ARM core | ||||||
|  | 	 */ | ||||||
|  | 	if (sec_in32(CAAM_SMPO_0) & PARTITION_OWNER(partition_num)) { | ||||||
|  | 		temp_reg = secmem_set_cmd(PARTITION(partition_num) | | ||||||
|  | 						CMD_PART_DEALLOC); | ||||||
|  | 		if (temp_reg & SMCSJR_AERR) { | ||||||
|  | 			printf("Error: De-allocation status 0x%X\n", temp_reg); | ||||||
|  | 			return ERROR_IN_PAGE_ALLOC; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* set the access rights to allow full access */ | ||||||
|  | 	sec_out32(CAAM_SMAG1JR0(partition_num), 0xF); | ||||||
|  | 	sec_out32(CAAM_SMAG2JR0(partition_num), 0xF); | ||||||
|  | 	sec_out32(CAAM_SMAPJR0(partition_num), 0xFF); | ||||||
|  | 
 | ||||||
|  | 	/* Now need to allocate partition_num of secure RAM. */ | ||||||
|  | 	/* De-Allocate page_num by starting with a page inquiry command */ | ||||||
|  | 	temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY); | ||||||
|  | 
 | ||||||
|  | 	/* if the page is owned, de-allocate it */ | ||||||
|  | 	if ((temp_reg & SMCSJR_PO) == PAGE_OWNED) { | ||||||
|  | 		temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_PAGE_DEALLOC); | ||||||
|  | 		if (temp_reg & SMCSJR_AERR) { | ||||||
|  | 			printf("Error: Allocation status 0x%X\n", temp_reg); | ||||||
|  | 			return ERROR_IN_PAGE_ALLOC; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Allocate page_num to partition_num */ | ||||||
|  | 	temp_reg = secmem_set_cmd(PAGE(page_num) | PARTITION(partition_num) | ||||||
|  | 						| CMD_PAGE_ALLOC); | ||||||
|  | 	if (temp_reg & SMCSJR_AERR) { | ||||||
|  | 		printf("Error: Allocation status 0x%X\n", temp_reg); | ||||||
|  | 		return ERROR_IN_PAGE_ALLOC; | ||||||
|  | 	} | ||||||
|  | 	/* page inquiry command to ensure that the page was allocated */ | ||||||
|  | 	temp_reg = secmem_set_cmd(PAGE(page_num) | CMD_INQUIRY); | ||||||
|  | 
 | ||||||
|  | 	/* if the page is not owned => problem */ | ||||||
|  | 	if ((temp_reg & SMCSJR_PO) != PAGE_OWNED) { | ||||||
|  | 		printf("Allocation of page %d in partition %d failed 0x%X\n", | ||||||
|  | 		       temp_reg, page_num, partition_num); | ||||||
|  | 
 | ||||||
|  | 		return ERROR_IN_PAGE_ALLOC; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int inline_cnstr_jobdesc_blob_dek(uint32_t *desc, const uint8_t *plain_txt, | ||||||
|  | 				       uint8_t *dek_blob, uint32_t in_sz) | ||||||
|  | { | ||||||
|  | 	uint32_t ret = 0; | ||||||
|  | 	u32 aad_w1, aad_w2; | ||||||
|  | 	/* output blob will have 32 bytes key blob in beginning and
 | ||||||
|  | 	 * 16 byte HMAC identifier at end of data blob */ | ||||||
|  | 	uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE; | ||||||
|  | 	/* Setting HDR for blob */ | ||||||
|  | 	uint8_t wrapped_key_hdr[8] = {HDR_TAG, 0x00, WRP_HDR_SIZE + out_sz, | ||||||
|  | 			     HDR_PAR, HAB_MOD, HAB_ALG, in_sz, HAB_FLG}; | ||||||
|  | 
 | ||||||
|  | 	/* initialize the blob array */ | ||||||
|  | 	memset(dek_blob, 0, out_sz + 8); | ||||||
|  | 	/* Copy the header into the DEK blob buffer */ | ||||||
|  | 	memcpy(dek_blob, wrapped_key_hdr, sizeof(wrapped_key_hdr)); | ||||||
|  | 
 | ||||||
|  | 	/* allocating secure memory */ | ||||||
|  | 	ret = caam_page_alloc(PAGE_1, PARTITION_1); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	/* Write DEK to secure memory */ | ||||||
|  | 	memcpy((uint32_t *)SEC_MEM_PAGE1, (uint32_t *)plain_txt, in_sz); | ||||||
|  | 
 | ||||||
|  | 	unsigned long start = (unsigned long)SEC_MEM_PAGE1 & | ||||||
|  | 				~(ARCH_DMA_MINALIGN - 1); | ||||||
|  | 	unsigned long end = ALIGN(start + 0x1000, ARCH_DMA_MINALIGN); | ||||||
|  | 	flush_dcache_range(start, end); | ||||||
|  | 
 | ||||||
|  | 	/* Now configure the access rights of the partition */ | ||||||
|  | 	sec_out32(CAAM_SMAG1JR0(PARTITION_1), KS_G1); /* set group 1 */ | ||||||
|  | 	sec_out32(CAAM_SMAG2JR0(PARTITION_1), 0);     /* clear group 2 */ | ||||||
|  | 	sec_out32(CAAM_SMAPJR0(PARTITION_1), PERM);   /* set perm & locks */ | ||||||
|  | 
 | ||||||
|  | 	/* construct aad for AES */ | ||||||
|  | 	aad_w1 = (in_sz << OP_ALG_ALGSEL_SHIFT) | KEY_AES_SRC | LD_CCM_MODE; | ||||||
|  | 	aad_w2 = 0x0; | ||||||
|  | 
 | ||||||
|  | 	init_job_desc(desc, 0); | ||||||
|  | 
 | ||||||
|  | 	append_cmd(desc, CMD_LOAD | CLASS_2 | KEY_IMM | KEY_ENC | | ||||||
|  | 				(0x0c << LDST_OFFSET_SHIFT) | 0x08); | ||||||
|  | 
 | ||||||
|  | 	append_u32(desc, aad_w1); | ||||||
|  | 
 | ||||||
|  | 	append_u32(desc, aad_w2); | ||||||
|  | 
 | ||||||
|  | 	append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR); | ||||||
|  | 
 | ||||||
|  | 	append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR); | ||||||
|  | 
 | ||||||
|  | 	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | | ||||||
|  | 						OP_PCLID_SECMEM); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| void inline_cnstr_jobdesc_hash(uint32_t *desc, | void inline_cnstr_jobdesc_hash(uint32_t *desc, | ||||||
| 			  const uint8_t *msg, uint32_t msgsz, uint8_t *digest, | 			  const uint8_t *msg, uint32_t msgsz, uint8_t *digest, | ||||||
|  |  | ||||||
|  | @ -14,6 +14,20 @@ | ||||||
| 
 | 
 | ||||||
| #define KEY_IDNFR_SZ_BYTES		16 | #define KEY_IDNFR_SZ_BYTES		16 | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_CMD_DEKBLOB | ||||||
|  | /* inline_cnstr_jobdesc_blob_dek:
 | ||||||
|  |  * Intializes and constructs the job descriptor for DEK encapsulation | ||||||
|  |  * using the given parameters. | ||||||
|  |  * @desc: reference to the job descriptor | ||||||
|  |  * @plain_txt: reference to the DEK | ||||||
|  |  * @enc_blob: reference where to store the blob | ||||||
|  |  * @in_sz: size in bytes of the DEK | ||||||
|  |  * @return: 0 on success, ECONSTRJDESC otherwise | ||||||
|  |  */ | ||||||
|  | int inline_cnstr_jobdesc_blob_dek(uint32_t *desc, const uint8_t *plain_txt, | ||||||
|  | 				uint8_t *enc_blob, uint32_t in_sz); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| void inline_cnstr_jobdesc_hash(uint32_t *desc, | void inline_cnstr_jobdesc_hash(uint32_t *desc, | ||||||
| 			  const uint8_t *msg, uint32_t msgsz, uint8_t *digest, | 			  const uint8_t *msg, uint32_t msgsz, uint8_t *digest, | ||||||
| 			  u32 alg_type, uint32_t alg_size, int sg_tbl); | 			  u32 alg_type, uint32_t alg_size, int sg_tbl); | ||||||
|  |  | ||||||
|  | @ -90,11 +90,13 @@ static int jr_init(void) | ||||||
| 	jr.liodn = DEFAULT_JR_LIODN; | 	jr.liodn = DEFAULT_JR_LIODN; | ||||||
| #endif | #endif | ||||||
| 	jr.size = JR_SIZE; | 	jr.size = JR_SIZE; | ||||||
| 	jr.input_ring = (dma_addr_t *)malloc(JR_SIZE * sizeof(dma_addr_t)); | 	jr.input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN, | ||||||
|  | 				JR_SIZE * sizeof(dma_addr_t)); | ||||||
| 	if (!jr.input_ring) | 	if (!jr.input_ring) | ||||||
| 		return -1; | 		return -1; | ||||||
| 	jr.output_ring = | 	jr.output_ring = | ||||||
| 	    (struct op_ring *)malloc(JR_SIZE * sizeof(struct op_ring)); | 	    (struct op_ring *)memalign(ARCH_DMA_MINALIGN, | ||||||
|  | 				JR_SIZE * sizeof(struct op_ring)); | ||||||
| 	if (!jr.output_ring) | 	if (!jr.output_ring) | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
|  | @ -163,13 +165,23 @@ static int jr_enqueue(uint32_t *desc_addr, | ||||||
| 	    CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0) | 	    CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0) | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
| 	jr.input_ring[head] = desc_phys_addr; |  | ||||||
| 	jr.info[head].desc_phys_addr = desc_phys_addr; | 	jr.info[head].desc_phys_addr = desc_phys_addr; | ||||||
| 	jr.info[head].desc_addr = (uint32_t)desc_addr; | 	jr.info[head].desc_addr = (uint32_t)desc_addr; | ||||||
| 	jr.info[head].callback = (void *)callback; | 	jr.info[head].callback = (void *)callback; | ||||||
| 	jr.info[head].arg = arg; | 	jr.info[head].arg = arg; | ||||||
| 	jr.info[head].op_done = 0; | 	jr.info[head].op_done = 0; | ||||||
| 
 | 
 | ||||||
|  | 	unsigned long start = (unsigned long)&jr.info[head] & | ||||||
|  | 					~(ARCH_DMA_MINALIGN - 1); | ||||||
|  | 	unsigned long end = ALIGN(start + sizeof(struct jr_info), | ||||||
|  | 					ARCH_DMA_MINALIGN); | ||||||
|  | 	flush_dcache_range(start, end); | ||||||
|  | 
 | ||||||
|  | 	jr.input_ring[head] = desc_phys_addr; | ||||||
|  | 	start = (unsigned long)&jr.input_ring[head] & ~(ARCH_DMA_MINALIGN - 1); | ||||||
|  | 	end = ALIGN(start + sizeof(dma_addr_t), ARCH_DMA_MINALIGN); | ||||||
|  | 	flush_dcache_range(start, end); | ||||||
|  | 
 | ||||||
| 	jr.head = (head + 1) & (jr.size - 1); | 	jr.head = (head + 1) & (jr.size - 1); | ||||||
| 
 | 
 | ||||||
| 	sec_out32(®s->irja, 1); | 	sec_out32(®s->irja, 1); | ||||||
|  | @ -187,6 +199,13 @@ static int jr_dequeue(void) | ||||||
| 	void *arg = NULL; | 	void *arg = NULL; | ||||||
| 
 | 
 | ||||||
| 	while (sec_in32(®s->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) { | 	while (sec_in32(®s->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) { | ||||||
|  | 		unsigned long start = (unsigned long)jr.output_ring & | ||||||
|  | 					~(ARCH_DMA_MINALIGN - 1); | ||||||
|  | 		unsigned long end = ALIGN(start + | ||||||
|  | 					  sizeof(struct op_ring)*JR_SIZE, | ||||||
|  | 					  ARCH_DMA_MINALIGN); | ||||||
|  | 		invalidate_dcache_range(start, end); | ||||||
|  | 
 | ||||||
| 		found = 0; | 		found = 0; | ||||||
| 
 | 
 | ||||||
| 		dma_addr_t op_desc = jr.output_ring[jr.tail].desc; | 		dma_addr_t op_desc = jr.output_ring[jr.tail].desc; | ||||||
|  | @ -333,13 +352,17 @@ static int instantiate_rng(void) | ||||||
| 
 | 
 | ||||||
| 	memset(&op, 0, sizeof(struct result)); | 	memset(&op, 0, sizeof(struct result)); | ||||||
| 
 | 
 | ||||||
| 	desc = malloc(sizeof(int) * 6); | 	desc = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * 6); | ||||||
| 	if (!desc) { | 	if (!desc) { | ||||||
| 		printf("cannot allocate RNG init descriptor memory\n"); | 		printf("cannot allocate RNG init descriptor memory\n"); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	inline_cnstr_jobdesc_rng_instantiation(desc); | 	inline_cnstr_jobdesc_rng_instantiation(desc); | ||||||
|  | 	int size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN); | ||||||
|  | 	flush_dcache_range((unsigned long)desc, | ||||||
|  | 			   (unsigned long)desc + size); | ||||||
|  | 
 | ||||||
| 	ret = run_descriptor_jr(desc); | 	ret = run_descriptor_jr(desc); | ||||||
| 
 | 
 | ||||||
| 	if (ret) | 	if (ret) | ||||||
|  |  | ||||||
|  | @ -135,7 +135,7 @@ typedef struct ccsr_sec { | ||||||
| #define CONFIG_JRSTARTR_JR0		0x00000001 | #define CONFIG_JRSTARTR_JR0		0x00000001 | ||||||
| 
 | 
 | ||||||
| struct jr_regs { | struct jr_regs { | ||||||
| #ifdef CONFIG_SYS_FSL_SEC_LE | #if defined(CONFIG_SYS_FSL_SEC_LE) && !defined(CONFIG_MX6) | ||||||
| 	u32 irba_l; | 	u32 irba_l; | ||||||
| 	u32 irba_h; | 	u32 irba_h; | ||||||
| #else | #else | ||||||
|  | @ -148,7 +148,7 @@ struct jr_regs { | ||||||
| 	u32 irsa; | 	u32 irsa; | ||||||
| 	u32 rsvd3; | 	u32 rsvd3; | ||||||
| 	u32 irja; | 	u32 irja; | ||||||
| #ifdef CONFIG_SYS_FSL_SEC_LE | #if defined(CONFIG_SYS_FSL_SEC_LE) && !defined(CONFIG_MX6) | ||||||
| 	u32 orba_l; | 	u32 orba_l; | ||||||
| 	u32 orba_h; | 	u32 orba_h; | ||||||
| #else | #else | ||||||
|  | @ -180,7 +180,7 @@ struct jr_regs { | ||||||
|  * related information |  * related information | ||||||
|  */ |  */ | ||||||
| struct sg_entry { | struct sg_entry { | ||||||
| #ifdef CONFIG_SYS_FSL_SEC_LE | #ifdef defined(CONFIG_SYS_FSL_SEC_LE) && !defined(CONFIG_MX6) | ||||||
| 	uint32_t addr_lo;	/* Memory Address - lo */ | 	uint32_t addr_lo;	/* Memory Address - lo */ | ||||||
| 	uint16_t addr_hi;	/* Memory Address of start of buffer - hi */ | 	uint16_t addr_hi;	/* Memory Address of start of buffer - hi */ | ||||||
| 	uint16_t reserved_zero; | 	uint16_t reserved_zero; | ||||||
|  | @ -201,7 +201,79 @@ struct sg_entry { | ||||||
| #define SG_ENTRY_OFFSET_SHIFT	0 | #define SG_ENTRY_OFFSET_SHIFT	0 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_MX6 | ||||||
|  | /* CAAM Job Ring 0 Registers */ | ||||||
|  | /* Secure Memory Partition Owner register */ | ||||||
|  | #define SMCSJR_PO		(3 << 6) | ||||||
|  | /* JR Allocation Error */ | ||||||
|  | #define SMCSJR_AERR		(3 << 12) | ||||||
|  | /* Secure memory partition 0 page 0 owner register */ | ||||||
|  | #define CAAM_SMPO_0		CONFIG_SYS_FSL_SEC_ADDR + 0x1FBC | ||||||
|  | /* Secure memory command register */ | ||||||
|  | #define CAAM_SMCJR0		CONFIG_SYS_FSL_SEC_ADDR + 0x10f4 | ||||||
|  | /* Secure memory command status register */ | ||||||
|  | #define CAAM_SMCSJR0		CONFIG_SYS_FSL_SEC_ADDR + 0x10fc | ||||||
|  | /* Secure memory access permissions register */ | ||||||
|  | #define CAAM_SMAPJR0(y)	(CONFIG_SYS_FSL_SEC_ADDR + 0x1104 + y*16) | ||||||
|  | /* Secure memory access group 2 register */ | ||||||
|  | #define CAAM_SMAG2JR0(y)	(CONFIG_SYS_FSL_SEC_ADDR + 0x1108 + y*16) | ||||||
|  | /* Secure memory access group 1 register */ | ||||||
|  | #define CAAM_SMAG1JR0(y)	(CONFIG_SYS_FSL_SEC_ADDR + 0x110C + y*16) | ||||||
|  | 
 | ||||||
|  | /* Commands and macros for secure memory */ | ||||||
|  | #define CMD_PAGE_ALLOC		0x1 | ||||||
|  | #define CMD_PAGE_DEALLOC	0x2 | ||||||
|  | #define CMD_PART_DEALLOC	0x3 | ||||||
|  | #define CMD_INQUIRY		0x5 | ||||||
|  | #define CMD_COMPLETE		(3 << 14) | ||||||
|  | #define PAGE_AVAILABLE		0 | ||||||
|  | #define PAGE_OWNED		(3 << 6) | ||||||
|  | #define PAGE(x)			(x << 16) | ||||||
|  | #define PARTITION(x)		(x << 8) | ||||||
|  | #define PARTITION_OWNER(x)	(0x3 << (x*2)) | ||||||
|  | 
 | ||||||
|  | /* Address of secure 4kbyte pages */ | ||||||
|  | #define SEC_MEM_PAGE0		CAAM_ARB_BASE_ADDR | ||||||
|  | #define SEC_MEM_PAGE1		(CAAM_ARB_BASE_ADDR + 0x1000) | ||||||
|  | #define SEC_MEM_PAGE2		(CAAM_ARB_BASE_ADDR + 0x2000) | ||||||
|  | #define SEC_MEM_PAGE3		(CAAM_ARB_BASE_ADDR + 0x3000) | ||||||
|  | 
 | ||||||
|  | #define JR_MID			2               /* Matches ROM configuration */ | ||||||
|  | #define KS_G1			(1 << JR_MID)   /* CAAM only */ | ||||||
|  | #define PERM			0x0000B008      /* Clear on release, lock SMAP | ||||||
|  | 						 * lock SMAG group 1 Blob */ | ||||||
|  | 
 | ||||||
|  | #define BLOB_SIZE(x)       (x + 32 + 16) /* Blob buffer size */ | ||||||
|  | 
 | ||||||
|  | /* HAB WRAPPED KEY header */ | ||||||
|  | #define WRP_HDR_SIZE		0x08 | ||||||
|  | #define HDR_TAG			0x81 | ||||||
|  | #define HDR_PAR			0x41 | ||||||
|  | /* HAB WRAPPED KEY Data */ | ||||||
|  | #define HAB_MOD			0x66 | ||||||
|  | #define HAB_ALG			0x55 | ||||||
|  | #define HAB_FLG			0x00 | ||||||
|  | 
 | ||||||
|  | /* Partition and Page IDs */ | ||||||
|  | #define PARTITION_1	1 | ||||||
|  | #define PAGE_1			1 | ||||||
|  | 
 | ||||||
|  | #define ERROR_IN_PAGE_ALLOC	1 | ||||||
|  | #define ECONSTRJDESC   -1 | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| int sec_init(void); | int sec_init(void); | ||||||
|  | 
 | ||||||
|  | /* blob_dek:
 | ||||||
|  |  * Encapsulates the src in a secure blob and stores it dst | ||||||
|  |  * @src: reference to the plaintext | ||||||
|  |  * @dst: reference to the output adrress | ||||||
|  |  * @len: size in bytes of src | ||||||
|  |  * @return: 0 on success, error otherwise | ||||||
|  |  */ | ||||||
|  | int blob_dek(const u8 *src, u8 *dst, u8 len); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #endif /* __FSL_SEC_H */ | #endif /* __FSL_SEC_H */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue