1 /*
2  * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdbool.h>
10 #include <limits.h>
11 #include "cc_otp_defs.h"
12 #include "cc_pal_mem.h"
13 #include "cc_pal_init.h"
14 #include "cc_pal_mutex_plat.h"
15 #include "prod_hw_defs.h"
16 #include "cc_production_asset.h"
17 #include "cc_pal_log.h"
18 #include "cc_prod_error.h"
19 #include "prod_crypto_driver.h"
20 #include "dx_crys_kernel.h"
21 #include "dx_id_registers.h"
22 #include "aes_driver.h"
23 #include "prod_util.h"
24 
25 
26 /**
27  * @brief This function
28  *
29  * @param[in]       package buffer(64 bytes),
30  *                          asset ID(4 bytes),
31  *                          label(7 bytes),
32  *                          context (16 bytes)
33  *
34  * @param[out]     plain asset (16 bytes)
35  *
36  * @return 0 -success; otherwise failure
37 
38  */
CC_PROD_PkgVerify(CCProdAssetPkg_t * pPkgAsset,const uint8_t * pAssetId,uint32_t assetIdSize,const uint8_t * pLabel,uint32_t labelSize,uint8_t * pContext,uint32_t contextSize,CCPlainAsset_t plainAsset,unsigned long workspaceAddr,uint32_t workspaceSize)39 uint32_t CC_PROD_PkgVerify(CCProdAssetPkg_t *pPkgAsset,
40                             const uint8_t      *pAssetId, uint32_t assetIdSize,
41                             const uint8_t     *pLabel, uint32_t labelSize,
42                             uint8_t     *pContext, uint32_t contextSize,
43                             CCPlainAsset_t plainAsset,
44                                unsigned long workspaceAddr,
45                             uint32_t     workspaceSize) {
46         uint32_t rc = 0;
47         uint8_t     tmpKey[PROD_KEY_TMP_KEY_SIZE] = { 0 };
48         uint8_t     provKey[PROD_KEY_TMP_KEY_SIZE] = { 0 };
49         uint8_t     provKeyLabel[] = PROD_LABEL;
50         CCProdAssetPkg_t localPkgAsset;
51 
52         /* Verify Inputs */
53         if ((pPkgAsset == NULL) ||
54             (pAssetId == NULL) || (assetIdSize == 0) ||
55             (pLabel == NULL) || (labelSize == 0) ||
56             (pContext == NULL) || (contextSize == 0) ||
57             (plainAsset == NULL)) {
58                 CC_PAL_LOG_ERR("Invalid inputs \n");
59                 return CC_PROD_INVALID_PARAM_ERR;
60         }
61 
62         /* Clear outputs */
63         CC_PalMemSetZero(plainAsset, sizeof(CCPlainAsset_t));
64 
65         /* Verify Package header */
66         if ((pPkgAsset->token != PROD_ASSET_PROV_TOKEN) ||
67             (pPkgAsset->version != PROD_ASSET_PROV_VERSION) ||
68             (pPkgAsset->assetSize != PROD_ASSET_SIZE) ||
69             (pPkgAsset->reserved[0] != PROD_ASSET_RESERVED1_VAL) ||
70             (pPkgAsset->reserved[1] != PROD_ASSET_RESERVED2_VAL)) {
71                 CC_PAL_LOG_ERR("Failed to parse Asset package \n");
72                 return CC_PROD_ASSET_PKG_PARAM_ERR;
73         }
74 
75         /* Derive temporary key */
76         // Calculate Ktmp = cmac(Krtl, 0x01 || ICV/OEM_label  || 0x0 || user context || 0x80)
77         rc = CC_PROD_KeyDerivation(RTL_KEY,   NULL,
78                                    pLabel, labelSize,
79                                    pContext, contextSize,
80                                    tmpKey);
81         if (rc != 0) {
82                 CC_PAL_LOG_ERR("failed to derive Ktmp, rc %d\n", rc);
83                 return CC_PROD_ASSET_PKG_VERIFY_ERR;
84         }
85 
86         /* Derive provisioning key */
87         // Calculate Kprov= cmac(Ktmp, 0x01 || "P"  || 0x0 || asset_id || 0x80)
88         rc = CC_PROD_KeyDerivation(USER_KEY, tmpKey,
89                                    provKeyLabel, sizeof(provKeyLabel)-1,
90                                    pAssetId, assetIdSize,
91                                    (uint8_t *)provKey);
92         if (rc != 0) {
93                 CC_PAL_LOG_ERR("failed to derive Kprov, rc %d\n", rc);
94                 return CC_PROD_ASSET_PKG_VERIFY_ERR;
95         }
96 
97         /* Decrypt and authenticate the asset */
98         // copy the package into local buffer to be physical and contig memory
99         CC_PalMemCopy((uint8_t *)&localPkgAsset, (uint8_t *)pPkgAsset, sizeof(CCProdAssetPkg_t));
100         rc = CC_PROD_AesCcmDecrypt(
101             provKey,         CC_PROD_AES_BLOCK_SIZE_IN_BYTES,
102             (uint8_t *)localPkgAsset.nonce, PROD_ASSET_NONCE_SIZE,
103             (uint8_t *)&localPkgAsset, PROD_ASSET_ADATA_SIZE,
104             (uint8_t *)localPkgAsset.encAsset, localPkgAsset.assetSize,
105             (uint8_t *)plainAsset,
106             PROD_ASSET_TAG_SIZE,  ((uint8_t *)localPkgAsset.encAsset) + localPkgAsset.assetSize,
107             workspaceAddr,
108             workspaceSize);
109         if (rc != 0) {
110                 CC_PAL_LOG_ERR("failed to CC_CommonAesCmacEncrypt() for Kprov, rc %d\n", rc);
111                 return CC_PROD_ASSET_PKG_VERIFY_ERR;
112         }
113 
114         return CC_OK;
115 }
116 
117 
CC_PROD_BitListFromNum(uint32_t * pWordBuff,uint32_t wordBuffSize,uint32_t numVal)118 uint32_t  CC_PROD_BitListFromNum(uint32_t *pWordBuff,
119                                         uint32_t wordBuffSize,
120                                         uint32_t numVal)
121 {
122         uint32_t  index = 0;
123         if (numVal != 0) {
124                 for (index = 0; index < wordBuffSize; index++) {
125                         pWordBuff[index] = CC_32BIT_MAX_VALUE >> (CC_BITS_IN_32BIT_WORD - PROD_MIN(numVal, CC_BITS_IN_32BIT_WORD));
126                         numVal -= PROD_MIN(numVal, CC_BITS_IN_32BIT_WORD);
127                 }
128                 if (numVal > 0) {
129                         CC_PalMemSetZero(pWordBuff, (wordBuffSize)*CC_32BIT_WORD_SIZE);
130                         return CC_PROD_INVALID_PARAM_ERR;
131                 }
132                 return CC_OK;
133         }
134         return CC_OK;
135 }
136 
137 
138 /* Count number of zeroes in 32-bit word */
CC_PROD_GetZeroCount(uint32_t * pBuff,uint32_t buffWordSize,uint32_t * pZeroCount)139 uint32_t  CC_PROD_GetZeroCount(uint32_t *pBuff,
140                                uint32_t buffWordSize,
141                                uint32_t  *pZeroCount)               {
142         uint32_t val;
143         uint32_t index = 0;
144 
145         *pZeroCount = 0;
146         for (index = 0; index < buffWordSize; index++) {
147                 val = pBuff[index];
148                 val = val - ((val >> 1) & 0x55555555);
149                 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
150                 val = ((((val + (val >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
151                 *pZeroCount += (32 - val);
152         }
153         /* All 0's and all 1's is forbidden */
154         if ((*pZeroCount == 0) || (*pZeroCount == buffWordSize*CC_BITS_IN_32BIT_WORD)) {
155                 *pZeroCount = 0;
156                 return CC_PROD_ILLEGAL_ZERO_COUNT_ERR;
157         }
158         return CC_OK;
159 }
160 
VerifyPidVal(void)161 static uint32_t VerifyPidVal(void)
162 {
163     uint32_t pidReg[CC_BSV_PID_SIZE_WORDS] = {0};
164     uint32_t pidVal1[CC_BSV_PID_SIZE_WORDS] = {CC_BSV_PID_0_VAL, CC_BSV_PID_1_VAL, CC_BSV_PID_2_VAL, CC_BSV_PID_3_VAL, CC_BSV_PID_4_VAL};
165     uint32_t pidVal2[CC_BSV_PID_SIZE_WORDS] = {CC_BSV_PID_0_VAL, CC_BSV_PID_1_VAL, CC_BSV_PID_2_1_VAL, CC_BSV_PID_3_VAL, CC_BSV_PID_4_VAL};
166 
167     pidReg[0] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, PERIPHERAL_ID_0));
168     pidReg[1] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, PERIPHERAL_ID_1));
169     pidReg[2] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, PERIPHERAL_ID_2));
170     pidReg[3] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, PERIPHERAL_ID_3));
171     pidReg[4] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, PERIPHERAL_ID_4));
172 
173     if ((CC_PalMemCmp((uint8_t*)pidVal1, (uint8_t*)pidReg, sizeof(pidVal1)) != 0) &&
174             (CC_PalMemCmp((uint8_t*)pidVal2, (uint8_t*)pidReg, sizeof(pidVal2)) != 0)) {
175         return CC_PROD_INIT_ERR;
176     }
177 
178     return CC_OK;
179 }
180 
VerifyCidVal(void)181 static uint32_t VerifyCidVal(void)
182 {
183     uint32_t cidReg[CC_BSV_CID_SIZE_WORDS] = {0};
184     uint32_t cidVal[CC_BSV_CID_SIZE_WORDS] = {CC_BSV_CID_0_VAL, CC_BSV_CID_1_VAL, CC_BSV_CID_2_VAL, CC_BSV_CID_3_VAL};
185 
186     cidReg[0] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, COMPONENT_ID_0));
187     cidReg[1] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, COMPONENT_ID_1));
188     cidReg[2] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, COMPONENT_ID_2));
189     cidReg[3] = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, COMPONENT_ID_3));
190 
191     if (CC_PalMemCmp((uint8_t*)cidVal, (uint8_t*)cidReg, sizeof(cidVal)) != 0){
192         return CC_PROD_INIT_ERR;
193     }
194 
195     return CC_OK;
196 }
197 
CCProd_Init(void)198 uint32_t  CCProd_Init(void)
199 {
200     uint32_t rc = CC_OK;
201     uint32_t reg = 0, tempVal = 0;
202 
203     rc = CC_PalInit();
204     if (rc != 0) {
205         return CC_PROD_INIT_ERR;
206     }
207 
208     /* verify peripheral ID (PIDR) */
209     rc = VerifyPidVal();
210     if (rc != 0) {
211         rc = CC_PROD_INIT_ERR;
212         goto end_init;
213     }
214 
215     /* verify component ID (CIDR) */
216     rc = VerifyCidVal();
217     if (rc != 0) {
218         rc = CC_PROD_INIT_ERR;
219         goto end_init;
220     }
221 
222     /* turn off the DFA since Cerberus doen't support it */
223     reg = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_AO_LOCK_BITS));
224     CC_REG_FLD_SET(0, HOST_AO_LOCK_BITS, HOST_FORCE_DFA_ENABLE, reg, 0x0);
225     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_AO_LOCK_BITS)  ,reg );
226     tempVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF,HOST_AO_LOCK_BITS));
227     if(tempVal != reg) {
228         rc = CC_PROD_INIT_ERR;
229         goto end_init;
230     }
231 
232     CC_REG_FLD_SET(0, HOST_AO_LOCK_BITS, HOST_DFA_ENABLE_LOCK, reg, CC_TRUE);
233     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_AO_LOCK_BITS)  ,reg );
234     tempVal = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF,HOST_AO_LOCK_BITS));
235     if(tempVal != reg) {
236         rc = CC_PROD_INIT_ERR;
237         goto end_init;
238     }
239 
240     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, AES_DFA_IS_ON), 0x0UL);
241 
242 #ifdef BIG__ENDIAN
243 /* Set DMA endianess to big */
244     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN), 0xCCUL);
245 #else /* LITTLE__ENDIAN */
246     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_ENDIAN), 0x00UL);
247 #endif
248 
249     end_init:
250     if (rc != CC_OK) {
251         CCPROD_Fini();
252     }
253     return rc;
254 }
255 
256 
CCPROD_Fini(void)257 void  CCPROD_Fini(void) {
258         CC_PalTerminate();
259 }
260