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_otp_defs.h"
8 #include "cc_pal_mem.h"
9 #include "dx_crys_kernel.h"
10 #include "prod_hw_defs.h"
11 #include "cc_pal_log.h"
12 #include "prod_util.h"
13 #include "cc_prod_error.h"
14 #include "cmpu_llf_rnd.h"
15 #include "prod_crypto_driver.h"
16 #include "cmpu_derivation.h"
17 #include "mbedtls_cc_mng_int.h"
18 #include "mbedtls_cc_mng.h"
19
20
CC_PROD_CalcHuk(uint32_t * pBuffForOtp,uint32_t * pManufactorWord,unsigned long workspaceAddr)21 static uint32_t CC_PROD_CalcHuk(uint32_t *pBuffForOtp,
22 uint32_t *pManufactorWord,
23 unsigned long workspaceAddr)
24 {
25 uint32_t error = 0;
26 uint32_t zeroCount = 0;
27 uint8_t pKey[CC_PROD_AES_Key256Bits_SIZE_IN_BYTES] = { 0 };
28 uint8_t pIv[CC_PROD_AES_IV_COUNTER_SIZE_IN_BYTES] = { 0 };
29 uint32_t *pEntrSrc;
30 uint32_t sourceSize;
31 uint32_t *pRndWorkBuff;
32
33 /*Call CC_PROD_LLF_RND_GetTrngSource to get entropy bits and to check entropy size*/
34 pRndWorkBuff = (uint32_t *)workspaceAddr;
35 error = CC_PROD_LLF_RND_GetTrngSource((uint32_t **)&pEntrSrc, &sourceSize, pRndWorkBuff);
36 if (error != CC_OK) {
37 CC_PAL_LOG_ERR("failed CC_PROD_LLF_RND_GetTrngSource, error is 0x%X\n", error);
38 return error;
39 }
40 error = CC_PROD_Derivation_Instantiate(pEntrSrc,
41 sourceSize,
42 pKey,
43 pIv);
44 if (error != CC_OK) {
45 CC_PAL_LOG_ERR("failed to CC_PROD_Derivation_Instantiate, error 0x%x\n", error);
46 return error;
47 }
48 error = CC_PROD_Derivation_Generate(pKey,
49 pIv,
50 pBuffForOtp,
51 CC_OTP_HUK_SIZE_IN_WORDS * sizeof(uint32_t));
52 if (error != CC_OK) {
53 CC_PAL_LOG_ERR("failed to CC_PROD_Derivation_Generate, error 0x%x\n", error);
54 return error;
55 }
56
57 error = CC_PROD_LLF_RND_VerifyGeneration((uint8_t *)pBuffForOtp);
58 if (error != CC_OK) {
59 CC_PAL_LOG_ERR("failed to CC_PROD_LLF_RND_VerifyGeneration, error 0x%x\n", error);
60 return error;
61 }
62
63 /*Count number of zero bits in HUK OTP fileds*/
64 error = CC_PROD_GetZeroCount(pBuffForOtp, CC_OTP_HUK_SIZE_IN_WORDS, &zeroCount);
65 if (error != CC_OK) {
66 CC_PAL_LOG_ERR("Invalid Huk zero count\n");
67 return error;
68 }
69
70 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, HUK_ZERO_BITS, zeroCount);
71 return CC_OK;
72 }
73
CC_PROD_HandleHbk0(CCCmpuData_t * pCmpuData,uint32_t * pHbk0BuffForOtp,uint32_t * pDcuLockBuffForOtp,uint32_t * pSwVerBuffForOtp,uint32_t * pManufactorWord)74 static uint32_t CC_PROD_HandleHbk0(CCCmpuData_t *pCmpuData,
75 uint32_t *pHbk0BuffForOtp,
76 uint32_t *pDcuLockBuffForOtp,
77 uint32_t *pSwVerBuffForOtp,
78 uint32_t *pManufactorWord)
79 {
80 uint32_t error = 0;
81 uint32_t zeroCount = 0;
82 uint32_t i = 0;
83 uint32_t icvOwnership = 0;
84 switch (pCmpuData->uniqueDataType){
85 case CMPU_UNIQUE_IS_USER_DATA:
86 /* If HBK not in use set the bit in manufactor flag */
87 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, HBK0_NOT_IN_USE, 1);
88 break;
89
90 case CMPU_UNIQUE_IS_HBK0:
91 /* Calculate HBK0 zeros */
92 CC_PalMemCopy(pHbk0BuffForOtp, pCmpuData->uniqueBuff.hbk0, CC_OTP_HBK0_SIZE_IN_WORDS * CC_32BIT_WORD_SIZE);
93 error = CC_PROD_GetZeroCount(pHbk0BuffForOtp, PROD_KEY_TMP_CONTEXT_WORD_SIZE, &zeroCount);
94 if (error != CC_OK) {
95 CC_PAL_LOG_ERR("Invalid Huk zero count\n");
96 return error;
97 }
98
99 /* Keep only ICV bit in DCU default locking */
100 for (i = 0; i < CC_OTP_DCU_SIZE_IN_WORDS; i++) {
101 icvOwnership = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, AO_ICV_DCU_RESTRICTION_MASK0) + (i * CC_32BIT_WORD_SIZE));
102 pDcuLockBuffForOtp[i] = pCmpuData->icvDcuDefaultLock[i] & icvOwnership;
103 }
104
105 /* set ICV minimum SW version */
106 error = CC_PROD_BitListFromNum(pSwVerBuffForOtp, CC_OTP_HBK0_MIN_VERSION_SIZE_IN_WORDS, pCmpuData->icvMinVersion);
107 if (error != CC_OK) {
108 CC_PAL_LOG_ERR("Failed to get bit list from number\n");
109 return error;
110 }
111 break;
112
113 default:
114 CC_PAL_LOG_ERR("Invalid unique data type \n");
115 return CC_PROD_INVALID_PARAM_ERR;
116 }
117
118 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, HBK0_ZERO_BITS, zeroCount);
119 return CC_OK;
120 }
121
122
CC_PROD_HandleKpicv(CCCmpuData_t * pCmpuData,uint32_t * pBuffForOtp,uint32_t * pManufactorWord,unsigned long workspaceAddr,uint32_t workspaceSize)123 static uint32_t CC_PROD_HandleKpicv(CCCmpuData_t *pCmpuData,
124 uint32_t *pBuffForOtp,
125 uint32_t *pManufactorWord,
126 unsigned long workspaceAddr,
127 uint32_t workspaceSize)
128 {
129 uint32_t error = 0;
130 uint32_t zeroCount = 0;
131
132 switch (pCmpuData->kpicvDataType) {
133 case ASSET_NO_KEY:
134 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, KPICV_NOT_IN_USE, 1);
135 goto end_kpicv;
136 case ASSET_PKG_KEY:
137 error = CC_PROD_PkgVerify((CCProdAssetPkg_t *)&pCmpuData->kpicv.pkgAsset,
138 (const uint8_t *)PROD_ICV_PROV_CONTEXT, PROD_KPROV_CONTEXT_SIZE,
139 (const uint8_t *)PROD_ICV_KEY_TMP_LABEL, PROD_KEY_TMP_LABEL_SIZE,
140 pCmpuData->uniqueBuff.hbk0, CC_OTP_HBK0_SIZE_IN_WORDS * CC_32BIT_WORD_SIZE,
141 (uint8_t * )pBuffForOtp,
142 workspaceAddr,
143 workspaceSize);
144 if (error != CC_OK) {
145 CC_PAL_LOG_ERR("failed to CC_PROD_PkgVerify fro Kpicv\n");
146 return error;
147 }
148 break;
149 case ASSET_PLAIN_KEY:
150 CC_PalMemCopy(pBuffForOtp, pCmpuData->kpicv.plainAsset, PROD_ASSET_SIZE);
151 break;
152 default:
153 CC_PAL_LOG_ERR("Inavlid key type for Kpicv\n");
154 return CC_PROD_INVALID_PARAM_ERR;
155 }
156 error = CC_PROD_GetZeroCount(pBuffForOtp, PROD_KEY_TMP_CONTEXT_WORD_SIZE, &zeroCount);
157 if (error != CC_OK) {
158 CC_PAL_LOG_ERR("Invalid zero count for Kpicv\n");
159 return error;
160 }
161 end_kpicv:
162 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, KPICV_ZERO_BITS, zeroCount);
163 return CC_OK;
164 }
165
166
CC_PROD_HandleKceicv(CCCmpuData_t * pCmpuData,uint32_t * pBuffForOtp,uint32_t * pManufactorWord,unsigned long workspaceAddr,uint32_t workspaceSize)167 static uint32_t CC_PROD_HandleKceicv(CCCmpuData_t *pCmpuData,
168 uint32_t *pBuffForOtp,
169 uint32_t *pManufactorWord,
170 unsigned long workspaceAddr,
171 uint32_t workspaceSize)
172 {
173 uint32_t error = 0;
174 uint32_t zeroCount = 0;
175
176 switch (pCmpuData->kceicvDataType) {
177 case ASSET_NO_KEY:
178 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, KCEICV_NOT_IN_USE, 1);
179 goto end_kceicv;
180 case ASSET_PKG_KEY:
181 error = CC_PROD_PkgVerify((CCProdAssetPkg_t *)&pCmpuData->kceicv.pkgAsset,
182 (const uint8_t *)PROD_ICV_ENC_CONTEXT, PROD_KPROV_CONTEXT_SIZE,
183 (const uint8_t *)PROD_ICV_KEY_TMP_LABEL, PROD_KEY_TMP_LABEL_SIZE,
184 pCmpuData->uniqueBuff.hbk0, CC_OTP_HBK0_SIZE_IN_WORDS * CC_32BIT_WORD_SIZE,
185 (uint8_t * )pBuffForOtp,
186 workspaceAddr,
187 workspaceSize);
188 if (error != CC_OK) {
189 CC_PAL_LOG_ERR("failed to CC_PROD_PkgVerify fro Kceicv\n");
190 return error;
191 }
192 break;
193 case ASSET_PLAIN_KEY:
194 CC_PalMemCopy(pBuffForOtp, pCmpuData->kceicv.plainAsset, PROD_ASSET_SIZE);
195 break;
196 default:
197 CC_PAL_LOG_ERR("Invalid key type for Kceicv\n");
198 return CC_PROD_INVALID_PARAM_ERR;
199 }
200
201 error = CC_PROD_GetZeroCount(pBuffForOtp, PROD_KEY_TMP_CONTEXT_WORD_SIZE, &zeroCount);
202 if (error != CC_OK) {
203 CC_PAL_LOG_ERR("Invalid zerocount for Kceicv\n");
204 return error;
205 }
206
207 end_kceicv:
208 SET_OTP_MANUFACTURE_FLAG(*pManufactorWord, KCEICV_ZERO_BITS, zeroCount);
209 return CC_OK;
210 }
211
212
213
CCProd_Cmpu(unsigned long ccHwRegBaseAddr,CCCmpuData_t * pCmpuData,unsigned long workspaceBaseAddr,uint32_t workspaceSize)214 CCError_t CCProd_Cmpu( unsigned long ccHwRegBaseAddr,
215 CCCmpuData_t *pCmpuData,
216 unsigned long workspaceBaseAddr,
217 uint32_t workspaceSize)
218 {
219 uint32_t error = 0;
220 uint32_t lcs = 0;
221 uint32_t manufactorWord = 0;
222 uint32_t hukBuffForOtp[CC_OTP_HUK_SIZE_IN_WORDS] = { 0 };
223 uint32_t hbk0BuffForOtp[CC_OTP_HBK0_SIZE_IN_WORDS] = { 0 };
224 uint32_t kpicvBuffForOtp[CC_OTP_KPICV_SIZE_IN_WORDS] = { 0 };
225 uint32_t kceicvBuffForOtp[CC_OTP_KCEICV_SIZE_IN_WORDS] = { 0 };
226 uint32_t icvLockBitsBuffForOtp[CC_OTP_DCU_SIZE_IN_WORDS] = { 0 };
227 uint32_t icvMinSwVersion[CC_OTP_HBK0_MIN_VERSION_SIZE_IN_WORDS] = { 0 };
228
229 if (sizeof(CCProdAssetPkg_t) != PROD_ASSET_PKG_SIZE) {
230 CC_PAL_LOG_ERR("invalid Pkg size\n");
231 return CC_PROD_INVALID_PARAM_ERR;
232 }
233 if ((pCmpuData == NULL) ||
234 (workspaceBaseAddr == 0) || //can not be zero because it is cast to a pointer later
235 (workspaceBaseAddr % CC_32BIT_WORD_SIZE) || // workspace address must be word aligned
236 (workspaceSize < CMPU_WORKSPACE_MINIMUM_SIZE) ) {
237 CC_PAL_LOG_ERR("invalid params\n");
238 return CC_PROD_INVALID_PARAM_ERR;
239 }
240
241 gCcRegBase = ccHwRegBaseAddr;
242
243 error = CCProd_Init();
244 if (error != CC_OK) {
245 CC_PAL_LOG_ERR("Failed to CCProd_Init 0x%x\n", error);
246 goto cmpuEnd;
247 }
248
249 /* Check LCS - CM only */
250 error = mbedtls_mng_lcsGet(&lcs);
251 if (error != CC_OK) {
252 CC_PAL_LOG_ERR("Failed to get LCS 0x%x \n", error);
253 goto cmpuEnd;
254 }
255
256 /* Verify LCS is CM */
257 if (lcs != CC_MNG_LCS_CM) {
258 CC_PAL_LOG_ERR("LCS is %d not valid\n", lcs);
259 error = CC_PROD_ILLEGAL_LCS_ERR;
260 goto cmpuEnd;
261 }
262
263 /* Genertae HUK */
264 error = CC_PROD_CalcHuk(hukBuffForOtp, &manufactorWord, workspaceBaseAddr);
265 if (error != CC_OK) {
266 CC_PAL_LOG_ERR("failed to CC_PROD_CalcHuk 0x%x \n", error);
267 goto cmpuEnd;
268 }
269
270 /* Set HBK0 if exists, and calculate its zero count. or set HBK0 not in use
271 Handle HBK0 dependencies: DCU lock bits and ICV minimum version */
272 error = CC_PROD_HandleHbk0(pCmpuData, hbk0BuffForOtp, icvLockBitsBuffForOtp, icvMinSwVersion, &manufactorWord);
273 if (error != CC_OK) {
274 CC_PAL_LOG_ERR("failed to CC_PROD_HandleHbk0 0x%x \n", error);
275 goto cmpuEnd;
276 }
277
278 /* Handle Kpicv, or set Kpicv not in use */
279 error = CC_PROD_HandleKpicv(pCmpuData, kpicvBuffForOtp, &manufactorWord, workspaceBaseAddr, workspaceSize);
280 if (error != CC_OK) {
281 CC_PAL_LOG_ERR("failed to CC_PROD_HandleKpicv 0x%x \n", error);
282 goto cmpuEnd;
283 }
284
285
286 /* Handle Kceicv, , or set Kceicv not in use */
287 error = CC_PROD_HandleKceicv(pCmpuData, kceicvBuffForOtp, &manufactorWord, workspaceBaseAddr, workspaceSize);
288 if (error != CC_OK) {
289 CC_PAL_LOG_ERR("failed to CC_PROD_HandleKceicv 0x%x \n", error);
290 goto cmpuEnd;
291 }
292
293 /* First, Burn Manufactor flag, including not in use flags set by ahndle functions above */
294 CC_PROD_OTP_WRITE_VERIFY_WORD(CC_OTP_MANUFACTURE_FLAG_OFFSET, manufactorWord, error);
295 if (error != CC_OK) {
296 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
297 goto cmpuEnd;
298 }
299
300 /* Burn Huk */
301 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_HUK_OFFSET, hukBuffForOtp, CC_OTP_HUK_SIZE_IN_WORDS, error);
302 if (error != CC_OK) {
303 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
304 goto cmpuEnd;
305 }
306
307 /* Burn HBK0 and its dependencies: DCU lock bits and SW version */
308 if (pCmpuData->uniqueDataType == CMPU_UNIQUE_IS_HBK0) {
309 /* HBK0 */
310 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_HBK0_OFFSET, hbk0BuffForOtp, CC_OTP_HBK0_SIZE_IN_WORDS, error);
311 if (error != CC_OK) {
312 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
313 goto cmpuEnd;
314 }
315 /* DCU lock bits */
316 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_DCU_OFFSET, icvLockBitsBuffForOtp, CC_OTP_DCU_SIZE_IN_WORDS, error);
317 if (error != CC_OK) {
318 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
319 goto cmpuEnd;
320 }
321 /* SW version */
322 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_HBK0_MIN_VERSION_OFFSET, icvMinSwVersion, CC_OTP_HBK0_MIN_VERSION_SIZE_IN_WORDS, error);
323 if (error != CC_OK) {
324 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
325 goto cmpuEnd;
326 }
327 }
328 /* Burn Kpicv */
329 if (pCmpuData->kpicvDataType != ASSET_NO_KEY) {
330 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_KPICV_OFFSET, kpicvBuffForOtp, CC_OTP_KPICV_SIZE_IN_WORDS, error);
331 if (error != CC_OK) {
332 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
333 goto cmpuEnd;
334 }
335 }
336 /* Burn Kceicv*/
337 if (pCmpuData->kceicvDataType != ASSET_NO_KEY) {
338 CC_PROD_OTP_WRITE_VERIFY_WORD_BUFF(CC_OTP_KCEICV_OFFSET, kceicvBuffForOtp, CC_OTP_KCEICV_SIZE_IN_WORDS, error);
339 if (error != CC_OK) {
340 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
341 goto cmpuEnd;
342 }
343 }
344 /* Burn icv configuration word */
345 CC_PROD_OTP_WRITE_VERIFY_WORD(CC_OTP_ICV_GENERAL_PURPOSE_FLAG_OFFSET,
346 pCmpuData->icvConfigWord,
347 error);
348 if (error != CC_OK) {
349 CC_PAL_LOG_ERR("Failed to verify OTP write 0x%x \n", error);
350 goto cmpuEnd;
351 }
352
353 cmpuEnd:
354 CC_PalMemSetZero((uint8_t *)workspaceBaseAddr, workspaceSize);
355 if (error != CC_OK) {
356 CC_PAL_LOG_ERR("CMPU failed, error = 0x%x \n", error);
357 }
358 CCPROD_Fini();
359 return error;
360 }
361
362
363
364