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