1 /*
2 * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7
8 /************* Include Files ****************/
9 #include "mbedtls_cc_mng.h"
10 #include "mbedtls_cc_mng_error.h"
11 #include "mbedtls_cc_mng_int.h"
12 #include "cc_pal_types.h"
13 #include "cc_pal_mem.h"
14 #include "cc_otp_defs.h"
15 #include "dx_id_registers.h"
16 #include "dx_crys_kernel.h"
17 #include "driver_defs.h"
18 #include "cc_pal_abort.h"
19 #include "cc_pal_mutex.h"
20 #include "cc_util_pm.h"
21
22 /************* Auxiliary API's *************/
23 /* All Musca-S1 platform-dependent defines (DX_PLAT_MUSCA_S1) are due to the
24 * fact that the S1 board's OTP is just an ordinary register which is volatile.
25 * The MRAM is used instead, and this is what the changes reflect.
26 */
mbedtls_mng_otpWordRead(uint32_t otpAddress,uint32_t * pOtpWord)27 int mbedtls_mng_otpWordRead(uint32_t otpAddress, uint32_t *pOtpWord)
28 {
29 uint32_t regVal=0;
30
31 /* check input variables */
32 if (pOtpWord == NULL) {
33 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
34 }
35
36 /* check otp limits */
37 CC_GET_OTP_LENGTH(regVal);
38 if (otpAddress >= regVal) {
39 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
40 }
41
42 /* read OTP word */
43 #ifdef DX_PLAT_MUSCA_S1
44 CC_READ_MRAM_WORD(otpAddress*sizeof(uint32_t), regVal);
45 #else
46 CC_READ_OTP_WORD(otpAddress*sizeof(uint32_t), regVal);
47 #endif
48 *pOtpWord = regVal;
49
50 return CC_OK;
51 }
52
mbedtls_mng_lcsGet(uint32_t * pLcs)53 int mbedtls_mng_lcsGet(uint32_t *pLcs)
54 {
55 #ifdef DX_PLAT_MUSCA_S1
56 uint32_t manufacturer_flag;
57 uint32_t oem_flag;
58
59 /* Read the MRAM (OTP) contents the CC312 uses to determine the lcs (for
60 * more information see Arm CryptoCell-312 Software Integrators Manual
61 * (r1p3), pgs. 3-36 - 3-38)
62 */
63 CC_READ_MRAM_WORD(CC_OTP_MANUFACTURE_FLAG_OFFSET * sizeof(uint32_t),
64 manufacturer_flag);
65
66 CC_READ_MRAM_WORD(CC_OTP_OEM_FLAG_OFFSET * sizeof(uint32_t), oem_flag);
67
68 if((manufacturer_flag == 0) && (oem_flag == 0))
69 *pLcs = CC_MNG_LCS_CM;
70 else if((manufacturer_flag != 0) && (oem_flag & 0xFF) == 0)
71 *pLcs = CC_MNG_LCS_DM;
72 else if((manufacturer_flag != 0) && (oem_flag & 0xFF) != 0)
73 *pLcs = CC_MNG_LCS_SEC_ENABLED;
74
75 return CC_OK;
76 #else
77 uint32_t regVal = 0;
78
79 /* check input variables */
80 if (pLcs == NULL) {
81 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
82 }
83
84 /* poll NVM register to assure that the NVM boot is finished (and LCS and the keys are valid) */
85 CC_WAIT_ON_NVM_IDLE_BIT();
86
87 /* read LCS register */
88 regVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, LCS_REG));
89
90 regVal = CC_REG_FLD_GET(0, LCS_REG, LCS_REG, regVal);
91
92 /* return the LCS value */
93 *pLcs = regVal;
94 return CC_OK;
95 #endif /* DX_PLAT_MUSCA_S1 */
96 }
97
mbedtls_mng_swVersionGet(mbedtls_mng_pubKeyType_t keyIndex,uint32_t * swVersion)98 int mbedtls_mng_swVersionGet(mbedtls_mng_pubKeyType_t keyIndex, uint32_t *swVersion)
99 {
100 uint32_t i, regVal = 0, tmpVal = 0;
101 uint32_t versionBitCount = 0;
102 uint32_t cntrWidth=0, cntrOffset=0, cntrSwVersion;
103 CCError_t error = CC_OK;
104 uint32_t lcs = 0, isHbkFull = 0;
105 CCBool_t isNextWordZero = CC_FALSE;
106
107 /* check swVersion pointrer */
108 if (swVersion == NULL) {
109 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
110 }
111
112 /* clear version in case of error */
113 *swVersion = 0;
114
115 /* get lifecycle */
116 error = mbedtls_mng_lcsGet(&lcs);
117 if (error != CC_OK) {
118 return error;
119 }
120
121 /* in case of RMA, return constant 0 */
122 if (lcs == CC_MNG_LCS_RMA){
123 return CC_OK;
124 }
125
126 /* get HBK configuration */
127 CC_IS_HBK_FULL(isHbkFull, error);
128 if (error != CC_OK)
129 return error;
130
131 /* check HBK configuration (in case of CM, get any counter needed) */
132 switch(keyIndex){
133 case CC_MNG_HASH_BOOT_KEY_256B:
134
135 /* verify correct HBK configuration for DM & SE */
136 if ((lcs != CC_MNG_LCS_CM) && (isHbkFull != CC_TRUE)) {
137 return CC_MNG_ILLEGAL_OPERATION_ERR;
138 }
139
140 cntrWidth = CC_OTP_HBK_MIN_VERSION_SIZE_IN_WORDS;
141 cntrOffset = CC_OTP_HBK_MIN_VERSION_OFFSET;
142 break;
143
144 case CC_MNG_HASH_BOOT_KEY_0_128B:
145
146 /* verify correct HBK configuration for DM & SE */
147 if ((lcs != CC_MNG_LCS_CM) && (isHbkFull == CC_TRUE)) {
148 return CC_MNG_ILLEGAL_OPERATION_ERR;
149 }
150
151 cntrWidth = CC_OTP_HBK0_MIN_VERSION_SIZE_IN_WORDS;
152 cntrOffset = CC_OTP_HBK0_MIN_VERSION_OFFSET;
153 break;
154
155 case CC_MNG_HASH_BOOT_KEY_1_128B:
156
157 /* verify correct HBK configuration for DM & SE */
158 if ((lcs != CC_MNG_LCS_CM) && (isHbkFull == CC_TRUE)) {
159 return CC_MNG_ILLEGAL_OPERATION_ERR;
160 }
161
162 cntrWidth = CC_OTP_HBK1_MIN_VERSION_SIZE_IN_WORDS;
163 cntrOffset = CC_OTP_HBK1_MIN_VERSION_OFFSET;
164 break;
165 default:
166 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
167 }
168
169 /* read the SW version from the OTP, and accumulate number of ones */
170 cntrSwVersion = 0;
171 for(i=0; i < cntrWidth; i++) {
172 error = mbedtls_mng_otpWordRead(cntrOffset+i, ®Val);
173 if (error != CC_OK)
174 return error;
175
176 CC_MNG_COUNT_ONE_BITS(regVal, versionBitCount);
177
178 /* verify legality of 1's bits */
179 if((isNextWordZero == CC_TRUE) && (regVal!=0)){
180 return CC_MNG_ILLEGAL_SW_VERSION_ERR;
181 }
182 if(versionBitCount < CC_MNG_ALL_ONES_NUM_BITS){
183 isNextWordZero = CC_TRUE;
184 }
185
186 /* convert versionBitCount to base-1 representation and compare to OTP word */
187 if(versionBitCount != 0){
188 tmpVal = CC_MNG_ALL_ONES_VALUE >> (CC_MNG_ALL_ONES_NUM_BITS - versionBitCount);
189 } else{
190 tmpVal = 0;
191 }
192 if (tmpVal != regVal) {
193 /* return error in case of invalid base-1 value */
194 return CC_MNG_ILLEGAL_SW_VERSION_ERR;
195 }
196
197 cntrSwVersion += versionBitCount;
198 }
199
200 *swVersion = cntrSwVersion;
201
202 return CC_OK;
203 }
204
mbedtls_mng_pubKeyHashGet(mbedtls_mng_pubKeyType_t keyIndex,uint32_t * hashedPubKey,uint32_t hashResultSizeWords)205 int mbedtls_mng_pubKeyHashGet(mbedtls_mng_pubKeyType_t keyIndex, uint32_t *hashedPubKey, uint32_t hashResultSizeWords)
206 {
207 uint32_t i, address;
208 uint32_t regVal = 0, cntZero = 0, zerosHash = 0;
209 uint32_t oemFlag = 0, icvFlag = 0;
210 CCError_t error = CC_OK;
211 uint32_t lcs = 0, isHbkFull = 0;
212
213 /* check hash buffer pointer */
214 if (hashedPubKey == NULL) {
215 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
216 }
217
218 /* get lifecycle */
219 error = mbedtls_mng_lcsGet(&lcs);
220 if (error != CC_OK) {
221 return error;
222 }
223
224 /* in case of CM, return error */
225 if (lcs == CC_MNG_LCS_CM) {
226 return CC_MNG_HASH_NOT_PROGRAMMED_ERR;
227 }
228
229 /* get HBK configuration */
230 CC_IS_HBK_FULL(isHbkFull, error);
231 if (error != CC_OK) {
232 return error;
233 }
234
235 /* read icv flags word */
236 error = mbedtls_mng_otpWordRead(CC_OTP_MANUFACTURE_FLAG_OFFSET, &icvFlag);
237 if (error != CC_OK) {
238 return error;
239 }
240
241 /* read OEM programmer flags word */
242 error = mbedtls_mng_otpWordRead(CC_OTP_OEM_FLAG_OFFSET, &oemFlag);
243 if (error != CC_OK)
244 return error;
245
246 /* verify validity of key index, key size and mode of operation */
247 switch (keyIndex) {
248 case CC_MNG_HASH_BOOT_KEY_256B:
249 /* key size should hold 256b */
250 if (hashResultSizeWords != CC_MNG_256B_HASH_SIZE_IN_WORDS)
251 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
252 /* otp shuld support full HBK */
253 if (isHbkFull != CC_TRUE) {
254 return CC_MNG_ILLEGAL_OPERATION_ERR;
255 }
256 /* Hbk0 zero count should be cleared */
257 if (CC_REG_FLD_GET2(0, OTP_MANUFACTURE_FLAG, HBK0_ZERO_BITS, icvFlag) != 0) {
258 return CC_MNG_ILLEGAL_OPERATION_ERR;
259 }
260
261 /* DM lcs is illegal for Hbk */
262 if (lcs == CC_MNG_LCS_DM) {
263 return CC_MNG_HASH_NOT_PROGRAMMED_ERR;
264 }
265
266 zerosHash = CC_REG_FLD_GET2(0, OTP_OEM_FLAG, HBK_ZERO_BITS, oemFlag);
267 address = CC_OTP_HBK_OFFSET;
268 break;
269
270 case CC_MNG_HASH_BOOT_KEY_0_128B:
271 /* key size should hold 128b */
272 if (hashResultSizeWords != CC_MNG_128B_HASH_SIZE_IN_WORDS)
273 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
274 /* otp shuld support 2 HBK's */
275 if (isHbkFull == CC_TRUE) {
276 return CC_MNG_ILLEGAL_OPERATION_ERR;
277 }
278
279 zerosHash = CC_REG_FLD_GET2(0, OTP_MANUFACTURE_FLAG, HBK0_ZERO_BITS, icvFlag);
280 address = CC_OTP_HBK0_OFFSET;
281 break;
282
283 case CC_MNG_HASH_BOOT_KEY_1_128B:
284 /* key size should hold 128b */
285 if (hashResultSizeWords != CC_MNG_128B_HASH_SIZE_IN_WORDS)
286 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
287 /* otp shuld support 2 HBK's */
288 if (isHbkFull == CC_TRUE) {
289 return CC_MNG_ILLEGAL_OPERATION_ERR;
290 }
291 /* DM lcs is illegal for Hbk1 */
292 if (lcs == CC_MNG_LCS_DM)
293 return CC_MNG_HASH_NOT_PROGRAMMED_ERR;
294
295 zerosHash = CC_REG_FLD_GET2(0, OTP_OEM_FLAG, HBK1_ZERO_BITS, oemFlag);
296 address = CC_OTP_HBK1_OFFSET;
297 break;
298
299 default:
300 return CC_MNG_ILLEGAL_INPUT_PARAM_ERR;
301 }
302
303 /* read hash key from OTP */
304 for (i = 0; i < hashResultSizeWords; i++) {
305 error = mbedtls_mng_otpWordRead(address + i, ®Val);
306 if (error != CC_OK) {
307 goto _Err_GetPubKey;
308 }
309 *(hashedPubKey + i) = regVal;
310
311 /* accumulate number of zeroes */
312 CC_MNG_COUNT_ZEROES(regVal, cntZero);
313 }
314
315 /* verify number of "0" bits in the hash key */
316 if (zerosHash == cntZero) {
317 return CC_OK;
318 } else {
319 error = CC_MNG_HBK_ZERO_COUNT_ERR;
320 }
321
322 /* case of error, clean hash buffer */
323 _Err_GetPubKey:
324 for (i = 0; i < hashResultSizeWords; i++) {
325 *(hashedPubKey + i) = 0;
326 }
327
328 return error;
329 }
330
331
332
333
334
335
336