1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "cc_dmpu.h"
8 #include "cc_otp_defs.h"
9 #include "cc_pal_mem.h"
10 #include "dx_crys_kernel.h"
11 #include "prod_hw_defs.h"
12 #include "cc_pal_log.h"
13 #include "prod_util.h"
14 #include "cc_prod_error.h"
15 #include "prod_crypto_driver.h"
16 #include "mbedtls_cc_mng_int.h"
17 #include "mbedtls_cc_mng.h"
18
CC_PROD_HandleKcp(CCDmpuData_t * pDmpuData,uint32_t * pBuffForOtp,uint32_t * pManufactorWord,unsigned long workspaceAddr,uint32_t workspaceSize)19 static uint32_t CC_PROD_HandleKcp(CCDmpuData_t *pDmpuData,
20 uint32_t *pBuffForOtp,
21 uint32_t *pManufactorWord,
22 unsigned long workspaceAddr,
23 uint32_t workspaceSize)
24 {
25 uint32_t error = 0;
26 uint32_t zeroCount = 0;
27
28 switch (pDmpuData->kcpDataType) {
29 case ASSET_NO_KEY:
30 SET_OTP_OEM_FLAG(*pManufactorWord, KCP_NOT_IN_USE, 1);
31 goto end_kcp;
32 case ASSET_PKG_KEY:
33 error = CC_PROD_PkgVerify((CCProdAssetPkg_t *)&pDmpuData->kcp.pkgAsset,
34 (const uint8_t *)PROD_OEM_PROV_CONTEXT, PROD_KPROV_CONTEXT_SIZE,
35 (const uint8_t *)PROD_OEM_KEY_TMP_LABEL, PROD_KEY_TMP_LABEL_SIZE,
36 (uint8_t *)pDmpuData->hbkBuff.hbk, CC_OTP_HBK1_SIZE_IN_WORDS * CC_32BIT_WORD_SIZE,
37 (uint8_t * )pBuffForOtp,
38 workspaceAddr,
39 workspaceSize);
40 if (error != CC_OK) {
41 CC_PAL_LOG_ERR("failed to CC_PROD_PkgVerify fro Kcp\n");
42 return error;
43 }
44 break;
45 case ASSET_PLAIN_KEY:
46 CC_PalMemCopy(pBuffForOtp, pDmpuData->kcp.plainAsset, PROD_ASSET_SIZE);
47 break;
48 default:
49 CC_PAL_LOG_ERR("Inavlid key type for Kcp\n");
50 return CC_PROD_INVALID_PARAM_ERR;
51 }
52 error = CC_PROD_GetZeroCount(pBuffForOtp, PROD_KEY_TMP_CONTEXT_WORD_SIZE, &zeroCount);
53 if (error != CC_OK) {
54 CC_PAL_LOG_ERR("Invalid zero count for Kcp\n");
55 return error;
56 }
57 end_kcp:
58 SET_OTP_OEM_FLAG(*pManufactorWord, KCP_ZERO_BITS, zeroCount);
59 return CC_OK;
60 }
61
62
CC_PROD_HandleKce(CCDmpuData_t * pDmpuData,uint32_t * pBuffForOtp,uint32_t * pManufactorWord,unsigned long workspaceAddr,uint32_t workspaceSize)63 static uint32_t CC_PROD_HandleKce(CCDmpuData_t *pDmpuData,
64 uint32_t *pBuffForOtp,
65 uint32_t *pManufactorWord,
66 unsigned long workspaceAddr,
67 uint32_t workspaceSize)
68 {
69 uint32_t error = 0;
70 uint32_t zeroCount = 0;
71
72 switch (pDmpuData->kceDataType) {
73 case ASSET_NO_KEY:
74 SET_OTP_OEM_FLAG(*pManufactorWord, KCE_NOT_IN_USE, 1);
75 goto end_kce;
76 case ASSET_PKG_KEY:
77 error = CC_PROD_PkgVerify((CCProdAssetPkg_t *)&pDmpuData->kce.pkgAsset,
78 (const uint8_t *)PROD_OEM_ENC_CONTEXT, PROD_KPROV_CONTEXT_SIZE,
79 (const uint8_t *)PROD_OEM_KEY_TMP_LABEL, PROD_KEY_TMP_LABEL_SIZE,
80 (uint8_t *)pDmpuData->hbkBuff.hbk, CC_OTP_HBK1_SIZE_IN_WORDS * CC_32BIT_WORD_SIZE,
81 (uint8_t * )pBuffForOtp,
82 workspaceAddr,
83 workspaceSize);
84 if (error != CC_OK) {
85 CC_PAL_LOG_ERR("failed to CC_PROD_PkgVerify fro Kce\n");
86 return error;
87 }
88 break;
89 case ASSET_PLAIN_KEY:
90 CC_PalMemCopy(pBuffForOtp, pDmpuData->kce.plainAsset, PROD_ASSET_SIZE);
91 break;
92 default:
93 CC_PAL_LOG_ERR("Invalid key type for Kce\n");
94 return CC_PROD_INVALID_PARAM_ERR;
95 }
96
97 error = CC_PROD_GetZeroCount(pBuffForOtp, PROD_KEY_TMP_CONTEXT_WORD_SIZE, &zeroCount);
98 if (error != CC_OK) {
99 CC_PAL_LOG_ERR("Invalid zerocount for Kce\n");
100 return error;
101 }
102
103 end_kce:
104 SET_OTP_OEM_FLAG(*pManufactorWord, KCE_ZERO_BITS, zeroCount);
105 return CC_OK;
106 }
107
108
109
CCProd_Dmpu(unsigned long ccHwRegBaseAddr,CCDmpuData_t * pDmpuData,unsigned long workspaceBaseAddr,uint32_t workspaceSize)110 CCError_t CCProd_Dmpu( unsigned long ccHwRegBaseAddr,
111 CCDmpuData_t *pDmpuData,
112 unsigned long workspaceBaseAddr,
113 uint32_t workspaceSize)
114 {
115 uint32_t error = 0;
116 uint32_t lcs = 0;
117 uint32_t manufactorWord = 0;
118 uint32_t icvWord = 0;
119 uint32_t hbkSizeInWords = 0;
120 uint32_t hbkOtpWordOffset = 0;
121 uint32_t swVerSizeInWords = 0;
122 uint32_t swVerOtpWordOffset = 0;
123 uint32_t zeroCount = 0;
124 uint32_t i = 0;
125 uint32_t icvOwnership = 0;
126 uint32_t hbkBuffForOtp[CC_OTP_HBK_SIZE_IN_WORDS] = { 0 };
127 uint32_t kcpBuffForOtp[CC_OTP_KCP_SIZE_IN_WORDS] = { 0 };
128 uint32_t kceBuffForOtp[CC_OTP_KCE_SIZE_IN_WORDS] = { 0 };
129 uint32_t dcuLockBitsBuffForOtp[CC_OTP_DCU_SIZE_IN_WORDS] = { 0 };
130 uint32_t oemMinSwVersion[CC_OTP_HBK_MIN_VERSION_SIZE_IN_WORDS] = { 0 };
131
132 if (sizeof(CCProdAssetPkg_t) != PROD_ASSET_PKG_SIZE) {
133 CC_PAL_LOG_ERR("invalid Pkg size\n");
134 return CC_PROD_INVALID_PARAM_ERR;
135 }
136 if ((pDmpuData == NULL) ||
137 (workspaceBaseAddr == 0) || //can not be zero because it is cast to a pointer later
138 (workspaceBaseAddr % CC_32BIT_WORD_SIZE) || // workspace address must be word aligned
139 (workspaceSize < DMPU_WORKSPACE_MINIMUM_SIZE)) {
140 CC_PAL_LOG_ERR("invalid params\n");
141 return CC_PROD_INVALID_PARAM_ERR;
142 }
143
144 gCcRegBase = ccHwRegBaseAddr;
145
146 error = CCProd_Init();
147 if (error != CC_OK) {
148 CC_PAL_LOG_ERR("Failed to CCProd_Init 0x%x\n", error);
149 goto dmpuEnd;
150 }
151
152 /* Check LCS - DM only */
153 error = mbedtls_mng_lcsGet(&lcs);
154 if (error != CC_OK) {
155 CC_PAL_LOG_ERR("Failed to get LCS 0x%x \n", error);
156 goto dmpuEnd;
157 }
158
159 /* Verify LCS is DM */
160 if (lcs != CC_MNG_LCS_DM) {
161 CC_PAL_LOG_ERR("LCS is %d not valid\n", lcs);
162 error = CC_PROD_ILLEGAL_LCS_ERR;
163 goto dmpuEnd;
164 }
165
166 /**************** Preparing and validating teh OEM assets ******************/
167 /* First, read ICV manufactor word to see if HBK0 exists */
168 CC_PROD_OTP_READ(icvWord, CC_OTP_MANUFACTURE_FLAG_OFFSET);
169 if (error != CC_OK) {
170 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
171 goto dmpuEnd;
172 }
173
174 switch (pDmpuData->hbkType) {
175 case DMPU_HBK_TYPE_HBK1:
176 if (!IS_HBK0_USED(icvWord)) {
177 CC_PAL_LOG_ERR("HBK type is not valid\n");
178 error = CC_PROD_ASSET_PKG_PARAM_ERR;
179 goto dmpuEnd;
180 }
181 hbkSizeInWords = CC_OTP_HBK1_SIZE_IN_WORDS;
182 hbkOtpWordOffset = CC_OTP_HBK1_OFFSET;
183 swVerOtpWordOffset = CC_OTP_HBK1_MIN_VERSION_OFFSET;
184 swVerSizeInWords = CC_OTP_HBK1_MIN_VERSION_SIZE_IN_WORDS;
185 break;
186 case DMPU_HBK_TYPE_HBK:
187 if (IS_HBK0_USED(icvWord)) {
188 CC_PAL_LOG_ERR("HBK type is not valid\n");
189 error = CC_PROD_ASSET_PKG_PARAM_ERR;
190 goto dmpuEnd;
191 }
192 hbkSizeInWords = CC_OTP_HBK_SIZE_IN_WORDS;
193 hbkOtpWordOffset = CC_OTP_HBK_OFFSET;
194 swVerOtpWordOffset = CC_OTP_HBK_MIN_VERSION_OFFSET;
195 swVerSizeInWords = CC_OTP_HBK_MIN_VERSION_SIZE_IN_WORDS;
196 break;
197 default:
198 CC_PAL_LOG_ERR("Invalid HBK type\n");
199 error = CC_PROD_ASSET_PKG_PARAM_ERR;
200 goto dmpuEnd;
201 }
202
203 /* Set HBK/1 buffer */
204 CC_PalMemCopy(hbkBuffForOtp, pDmpuData->hbkBuff.hbk, hbkSizeInWords * CC_32BIT_WORD_SIZE);
205 error = CC_PROD_GetZeroCount(hbkBuffForOtp, hbkSizeInWords, &zeroCount);
206 if (error != CC_OK) {
207 CC_PAL_LOG_ERR("Invalid Huk zero count\n");
208 goto dmpuEnd;
209 }
210
211 if (pDmpuData->hbkType == DMPU_HBK_TYPE_HBK) {
212 SET_OTP_OEM_FLAG(manufactorWord, HBK_ZERO_BITS, zeroCount);
213 } else { // type is DMPU_HBK_TYPE_HBK1
214 SET_OTP_OEM_FLAG(manufactorWord, HBK1_ZERO_BITS, zeroCount);
215 }
216 /* Set OEM minimum SW version according to HBK/1*/
217 error = CC_PROD_BitListFromNum(oemMinSwVersion, swVerSizeInWords, pDmpuData->oemMinVersion);
218 if (error != CC_OK) {
219 CC_PAL_LOG_ERR("Failed to get bit list from number\n");
220 goto dmpuEnd;
221 }
222
223 /* Handle Kcp, or set Kcp not in use */
224 error = CC_PROD_HandleKcp(pDmpuData, kcpBuffForOtp, &manufactorWord, workspaceBaseAddr, workspaceSize);
225 if (error != CC_OK) {
226 CC_PAL_LOG_ERR("failed to CC_PROD_HandleKcp 0x%x \n", error);
227 goto dmpuEnd;
228 }
229
230
231 /* Handle Kce, , or set Kce not in use */
232 error = CC_PROD_HandleKce(pDmpuData, kceBuffForOtp, &manufactorWord, workspaceBaseAddr, workspaceSize);
233 if (error != CC_OK) {
234 CC_PAL_LOG_ERR("failed to CC_PROD_HandleKce 0x%x \n", error);
235 goto dmpuEnd;
236 }
237
238 /* Keep only OEM bit in DCU default locking */
239 for (i = 0; i < CC_OTP_DCU_SIZE_IN_WORDS; i++) {
240 icvOwnership = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, AO_ICV_DCU_RESTRICTION_MASK0) + (i * CC_32BIT_WORD_SIZE));
241 dcuLockBitsBuffForOtp[i] = pDmpuData->oemDcuDefaultLock[i] & (~icvOwnership);
242 }
243
244 /**************** Burning OTP ******************/
245 /* First, Burn Manufactor flag, including not in use flags set by ahndle functions above */
246 CC_PROD_OTP_WRITE_VERIFY_WORD(CC_OTP_OEM_FLAG_OFFSET, manufactorWord, error);
247 if (error != CC_OK) {
248 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
249 goto dmpuEnd;
250 }
251
252 /* Burn HBK or HBK1 */
253 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(hbkOtpWordOffset, hbkBuffForOtp, hbkSizeInWords, error);
254 if (error != CC_OK) {
255 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
256 goto dmpuEnd;
257 }
258 /* DCU lock bits */
259 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_DCU_OFFSET, dcuLockBitsBuffForOtp, CC_OTP_DCU_SIZE_IN_WORDS, error);
260 if (error != CC_OK) {
261 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
262 goto dmpuEnd;
263 }
264 /* SW version */
265 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(swVerOtpWordOffset, oemMinSwVersion, swVerSizeInWords, error);
266 if (error != CC_OK) {
267 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
268 goto dmpuEnd;
269 }
270
271 /* Burn Kcp */
272 if (pDmpuData->kcpDataType != ASSET_NO_KEY) {
273 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_KCP_OFFSET, kcpBuffForOtp, CC_OTP_KCP_SIZE_IN_WORDS, error);
274 if (error != CC_OK) {
275 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
276 goto dmpuEnd;
277 }
278 }
279 /* Burn Kce*/
280 if (pDmpuData->kceDataType != ASSET_NO_KEY) {
281 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_KCE_OFFSET, kceBuffForOtp, CC_OTP_KCE_SIZE_IN_WORDS, error);
282 if (error != CC_OK) {
283 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
284 goto dmpuEnd;
285 }
286 }
287
288 dmpuEnd:
289 if (error != CC_OK) {
290 CC_PAL_LOG_ERR("DMPU failed, error = 0x%x \n", error);
291 }
292 CCPROD_Fini();
293 return error;
294 }
295
296
297
298