1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2016 Freescale Semiconductor, Inc.
4  * Copyright 2017 NXP
5  *
6  * These commands enable the use of the CAAM MPPubK-generation and MPSign
7  * functions in supported i.MX devices.
8  */
9 
10 #include <asm/byteorder.h>
11 #include <asm/arch/clock.h>
12 #include <linux/compiler.h>
13 #include <command.h>
14 #include <common.h>
15 #include <environment.h>
16 #include <fsl_sec.h>
17 #include <mapmem.h>
18 #include <memalign.h>
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 /**
23  * do_mfgprot() - Handle the "mfgprot" command-line command
24  * @cmdtp:  Command data struct pointer
25  * @flag:   Command flag
26  * @argc:   Command-line argument count
27  * @argv:   Array of command-line arguments
28  *
29  * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
30  * on error.
31  */
do_mfgprot(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])32 static int do_mfgprot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
33 {
34 	u8 *m_ptr, *dgst_ptr, *c_ptr, *d_ptr, *dst_ptr;
35 	char *pubk, *sign, *sel;
36 	int m_size, i, ret;
37 	u32 m_addr;
38 
39 	pubk = "pubk";
40 	sign = "sign";
41 	sel = argv[1];
42 
43 	/* Enable HAB clock */
44 	hab_caam_clock_enable(1);
45 
46 	u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR +
47 				   FSL_CAAM_ORSR_JRa_OFFSET);
48 
49 	if (out_jr_size != FSL_CAAM_MAX_JR_SIZE)
50 		sec_init();
51 
52 	if (strcmp(sel, pubk) == 0) {
53 		dst_ptr = malloc_cache_aligned(FSL_CAAM_MP_PUBK_BYTES);
54 		if (!dst_ptr)
55 			return -ENOMEM;
56 
57 		ret = gen_mppubk(dst_ptr);
58 		if (ret) {
59 			free(dst_ptr);
60 			return ret;
61 		}
62 
63 		/* Output results */
64 		puts("Public key:\n");
65 		for (i = 0; i < FSL_CAAM_MP_PUBK_BYTES; i++)
66 			printf("%02X", (dst_ptr)[i]);
67 		puts("\n");
68 		free(dst_ptr);
69 
70 	} else if (strcmp(sel, sign) == 0) {
71 		if (argc != 4)
72 			return CMD_RET_USAGE;
73 
74 		m_addr = simple_strtoul(argv[2], NULL, 16);
75 		m_size = simple_strtoul(argv[3], NULL, 10);
76 		m_ptr = map_physmem(m_addr, m_size, MAP_NOCACHE);
77 		if (!m_ptr)
78 			return -ENOMEM;
79 
80 		dgst_ptr = malloc_cache_aligned(FSL_CAAM_MP_MES_DGST_BYTES);
81 		if (!dgst_ptr) {
82 			ret = -ENOMEM;
83 			goto free_m;
84 		}
85 
86 		c_ptr = malloc_cache_aligned(FSL_CAAM_MP_PRVK_BYTES);
87 		if (!c_ptr) {
88 			ret = -ENOMEM;
89 			goto free_dgst;
90 		}
91 
92 		d_ptr = malloc_cache_aligned(FSL_CAAM_MP_PRVK_BYTES);
93 		if (!d_ptr) {
94 			ret = -ENOMEM;
95 			goto free_c;
96 		}
97 
98 		ret = sign_mppubk(m_ptr, m_size, dgst_ptr, c_ptr, d_ptr);
99 		if (ret)
100 			goto free_d;
101 
102 		/* Output results */
103 		puts("Message: ");
104 		for (i = 0; i < m_size; i++)
105 			printf("%02X ", (m_ptr)[i]);
106 		puts("\n");
107 
108 		puts("Message Representative Digest(SHA-256):\n");
109 		for (i = 0; i < FSL_CAAM_MP_MES_DGST_BYTES; i++)
110 			printf("%02X", (dgst_ptr)[i]);
111 		puts("\n");
112 
113 		puts("Signature:\n");
114 		puts("C:\n");
115 		for (i = 0; i < FSL_CAAM_MP_PRVK_BYTES; i++)
116 			printf("%02X", (c_ptr)[i]);
117 		puts("\n");
118 
119 		puts("d:\n");
120 		for (i = 0; i < FSL_CAAM_MP_PRVK_BYTES; i++)
121 			printf("%02X", (d_ptr)[i]);
122 		puts("\n");
123 free_d:
124 	free(d_ptr);
125 free_c:
126 	free(c_ptr);
127 free_dgst:
128 	free(dgst_ptr);
129 free_m:
130 	unmap_sysmem(m_ptr);
131 
132 	} else {
133 		return CMD_RET_USAGE;
134 	}
135 	return ret;
136 }
137 
138 /***************************************************/
139 static char mfgprot_help_text[] =
140 	"Usage:\n"
141 	 "Print the public key for Manufacturing Protection\n"
142 	 "\tmfgprot pubk\n"
143 	 "Generates a Manufacturing Protection signature\n"
144 	 "\tmfgprot sign <data_addr> <size>";
145 
146 U_BOOT_CMD(
147 	mfgprot, 4, 1, do_mfgprot,
148 	"Manufacturing Protection\n",
149 	mfgprot_help_text
150 );
151