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