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, &regVal);
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, &regVal);
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