1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #define CC_PAL_LOG_CUR_COMPONENT CC_LOG_MASK_SECURE_BOOT
8
9 /************* Include Files ****************/
10
11
12 #include "secureboot_error.h"
13 #include "secureboot_basetypes.h"
14 #include "secureboot_stage_defs.h"
15 #include "secureboot_gen_defs.h"
16 #include "secureboot_defs.h"
17 #include "bootimagesverifier_error.h"
18 #include "nvm_otp.h"
19 #include "cc_pal_log.h"
20 #include "secureboot_stage_defs.h"
21 #include "secdebug_defs.h"
22
23 /************************ Defines ******************************/
24
25 /************************ Enums ******************************/
26
27 /************************ Typedefs ******************************/
28
29 /************************ Global Data ******************************/
30
31 /************************ Internal Functions ******************************/
32
33 /************************ Public Functions ******************************/
34
CCSbImageLoadAndVerify(CCSbFlashReadFunc preHashflashRead_func,void * preHashUserContext,unsigned long hwBaseAddress,uint8_t isLoadFromFlash,uint8_t isVerifyImage,bsvCryptoMode_t cryptoMode,CCBsvKeyType_t keyType,AES_Iv_t AESIv,uint8_t * pSwRecSignedData,uint32_t * pSwRecNonSignedData,uint32_t * workspace_ptr,uint32_t workspaceSize)35 CCError_t CCSbImageLoadAndVerify(CCSbFlashReadFunc preHashflashRead_func,
36 void *preHashUserContext,
37 unsigned long hwBaseAddress,
38 uint8_t isLoadFromFlash,
39 uint8_t isVerifyImage,
40 bsvCryptoMode_t cryptoMode,
41 CCBsvKeyType_t keyType,
42 AES_Iv_t AESIv,
43 uint8_t *pSwRecSignedData,
44 uint32_t *pSwRecNonSignedData,
45 uint32_t *workspace_ptr,
46 uint32_t workspaceSize)
47 {
48 /* error variable */
49 CCError_t error = CC_OK;
50
51 ContentCertImageRecord_t cntImageRec;
52 CCSbSwImgAddData_t cntNonSignedImageRec;
53 CCHashResult_t actImageHash;
54 CCAddr_t currLoadStartAddress = 0;
55 uint32_t chunkSizeInBytes = 0;
56 uint32_t actualImageSize = 0;
57
58 /* Use user workspace in double buffer manner */
59 uint32_t *workRam1=NULL, *workRam2=NULL;
60 uint8_t isToggle = CC_FALSE, isLoadIV = CC_TRUE;
61
62 /*------------------
63 CODE
64 -------------------*/
65
66 /* In order to improve performance the Loading from Flash will be done simultaneously wit Hash calculation */
67
68 /* Initialize parameters */
69 UTIL_MemCopy((uint8_t *)&cntImageRec, (uint8_t *)pSwRecSignedData, sizeof(ContentCertImageRecord_t));
70 /* The non-signed is word aligned, so we can cast the pointer */
71 UTIL_MemCopy((uint8_t *)&cntNonSignedImageRec, (uint8_t *)pSwRecNonSignedData, sizeof(CCSbSwImgAddData_t));
72
73 actualImageSize = cntNonSignedImageRec.Len;
74 currLoadStartAddress = cntImageRec.loadAddr;
75
76 if (cntImageRec.isAesCodeEncUsed == 0){
77 /* overwrite crypto mode to hash only */
78 cryptoMode = BSV_CRYPTO_HASH;
79 keyType = CC_BSV_END_OF_KEY_TYPE;
80 } else {
81 /* verify crypto mode and key are set for aes */
82 if( (cryptoMode == BSV_CRYPTO_HASH) || (keyType == CC_BSV_END_OF_KEY_TYPE) ){
83 CC_PAL_LOG_ERR("AES operation is not configuraed correctly\n");
84 return CC_BOOT_IMG_VERIFIER_CERT_DECODING_ILLEGAL;
85 }
86 }
87
88 /* Validate image size */
89 if ((cntNonSignedImageRec.Len == 0) ||
90 (cntNonSignedImageRec.Len > cntImageRec.imageMaxSize)) {
91 CC_PAL_LOG_ERR("SW image size is illegal !\n");
92 return CC_BOOT_IMG_VERIFIER_SW_COMP_SIZE_IS_NULL;
93 }
94
95 /* Set chunk size for read and process data (fixed according to user workspace or HW limitation) */
96 chunkSizeInBytes = CC_DOUBLE_BUFFER_MAX_SIZE_IN_BYTES / 2;
97
98 /* In case of no loading address, we use user workspace in double buffer mode */
99 if (cntImageRec.loadAddr == CC_SW_COMP_NO_MEM_LOAD_INDICATION) {
100
101 isToggle = CC_TRUE;
102
103 /* The workspace minimum size must be at least CC_DOUBLE_BUFFER_MAX_SIZE_IN_BYTES,
104 if its not the function will return error (if temp memory should be used) */
105 if (workspaceSize < CC_DOUBLE_BUFFER_MAX_SIZE_IN_BYTES){
106
107 CC_PAL_LOG_ERR("workspace size too small\n");
108 return CC_BOOT_IMG_VERIFIER_WORKSPACE_SIZE_TOO_SMALL;
109 }
110
111 /* Divide the workspace into 2 buffers, in order to allow reading and calculating HASH
112 simultaneously , each buffer size is CC_DOUBLE_BUFFER_MAX_SIZE_IN_BYTES/2 */
113 workRam1 = workspace_ptr; /* Size of this section is CC_DOUBLE_BUFFER_MAX_SIZE_IN_BYTES/2 */
114 workRam2 = workspace_ptr + (CC_DOUBLE_BUFFER_MAX_SIZE_IN_BYTES/2)/sizeof(uint32_t);
115
116 /* Starting with the first buffer */
117 cntImageRec.loadAddr = CONVERT_TO_ADDR(workRam1);
118 }
119
120 if (isVerifyImage == CC_TRUE){
121
122 /* initialize the AES and HASH */
123 error = BsvCryptoImageInit(hwBaseAddress, cryptoMode, keyType);
124 if (error != CC_OK) {
125 CC_PAL_LOG_ERR("BsvCryptoImageInit failed 0x%xl !\n", error);
126 return error;
127 }
128 }
129
130 /* Load and/or Verify image in chunks */
131 /*------------------------------------*/
132 while (cntNonSignedImageRec.Len > 0) {
133
134 /* Set number of bytes to load and/or verify */
135 chunkSizeInBytes = min(chunkSizeInBytes, cntNonSignedImageRec.Len);
136
137 /* Copy data from the flash to memory with user callback */
138 if ( isLoadFromFlash == CC_TRUE) {
139 error = preHashflashRead_func(cntNonSignedImageRec.StoreAddr, (uint8_t*)(CONVERT_TO_ADDR(cntImageRec.loadAddr)),
140 chunkSizeInBytes, preHashUserContext);
141 if (error != CC_OK) {
142 CC_PAL_LOG_ERR("preHashflashRead_func failed 0x%xl !\n", error);
143 return error;
144 }
145 }
146
147 if (isVerifyImage == CC_TRUE){
148 /* Per chunk, run CC operation (hash + AES) in-place.
149 To improve performance, do not wait for completion operation */
150 error = BsvCryptoImageUpdate( hwBaseAddress, cryptoMode, keyType, (uint32_t *)AESIv,
151 (uint8_t *)(CONVERT_TO_ADDR(cntImageRec.loadAddr)),
152 (uint8_t *)(CONVERT_TO_ADDR(cntImageRec.loadAddr)),
153 chunkSizeInBytes, actImageHash, isLoadIV);
154 if (error != CC_OK) {
155 CC_PAL_LOG_ERR("BsvCryptoImageUpdate failed 0x%xl !\n", error);
156 return error;
157 }
158 isLoadIV = CC_FALSE;
159 }
160
161 /* Update for next chunk */
162 cntNonSignedImageRec.StoreAddr = (CCAddr_t)((unsigned long)cntNonSignedImageRec.StoreAddr + chunkSizeInBytes);
163 cntImageRec.loadAddr = (CCAddr_t)((unsigned long)cntImageRec.loadAddr + chunkSizeInBytes);
164 cntNonSignedImageRec.Len = cntNonSignedImageRec.Len - chunkSizeInBytes;
165
166 if (isToggle == CC_TRUE) {
167
168 /* Toggle on user's workspace (double buffer) */
169 if ( cntImageRec.loadAddr == CONVERT_TO_ADDR(workRam1) ){
170 cntImageRec.loadAddr = CONVERT_TO_ADDR(workRam2);
171 } else {
172 cntImageRec.loadAddr = CONVERT_TO_ADDR(workRam1);
173 }
174 }
175 }
176
177 if (isVerifyImage == CC_TRUE){
178
179 /* get Hash result and compare */
180 error = BsvCryptoImageFinish(hwBaseAddress, cryptoMode, actImageHash);
181 if (error != CC_OK){
182 CC_PAL_LOG_ERR("BsvCryptoImageFinish failed 0x%xl !\n", error);
183 return error;
184 }
185
186 error = UTIL_MemCmp((uint8_t *)cntImageRec.imageHash, (uint8_t *)actImageHash, HASH_RESULT_SIZE_IN_BYTES);
187 if (error != CC_TRUE){
188 CC_PAL_LOG_ERR("SW comp failed verification\n");
189 /* clear image in RAM in case of CC_SB_LOAD_AND_VERIFY scheme */
190 if ((isLoadFromFlash == CC_TRUE) && (isVerifyImage == CC_TRUE)
191 && (currLoadStartAddress != CC_SW_COMP_NO_MEM_LOAD_INDICATION)){
192 UTIL_MemSet((uint8_t*)currLoadStartAddress, 0, actualImageSize);
193 }
194 return CC_BOOT_IMG_VERIFIER_SW_COMP_FAILED_VERIFICATION;
195 }
196 }
197
198 return CC_OK;
199 }
200
201
CCSbSetNvCounter(unsigned long hwBaseAddress,CCSbCertInfo_t * certPkgInfo)202 CCError_t CCSbSetNvCounter(unsigned long hwBaseAddress, CCSbCertInfo_t *certPkgInfo)
203 {
204 CCError_t error = CC_OK;
205
206 if (NULL == certPkgInfo) {
207 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
208 }
209
210 /* if version is bigger, then set the new version in the otp */
211 if (certPkgInfo->activeMinSwVersionVal > certPkgInfo->otpVersion) {
212 error = NVM_SetSwVersion(hwBaseAddress, certPkgInfo->keyIndex, certPkgInfo->activeMinSwVersionVal);
213 if (CC_OK != error) {
214 return error;
215 }
216 }
217
218 return error;
219 }
220
CCSbVerifyNvCounter(unsigned long hwBaseAddress,uint32_t swVersion,CCSbCertInfo_t * certPkgInfo)221 CCError_t CCSbVerifyNvCounter(unsigned long hwBaseAddress, uint32_t swVersion, CCSbCertInfo_t *certPkgInfo)
222 {
223 CCError_t error = CC_OK;
224 uint32_t otpVersion;
225 uint8_t initFlag;
226 CCSbPubKeyIndexType_t keyIndex;
227 uint32_t activeNvCounterVal;
228
229 /* Validate input parameters */
230 if (NULL == certPkgInfo) {
231 CC_PAL_LOG_ERR("invalid inputs\n");
232 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
233 }
234
235 initFlag = certPkgInfo->initDataFlag;
236
237 keyIndex = certPkgInfo->keyIndex;
238
239 if (initFlag == 0) {
240 /* Get sw version from OTP */
241 error = NVM_GetSwVersion(hwBaseAddress, keyIndex, &otpVersion);
242 if (CC_OK != error) {
243 return error;
244 }
245
246 certPkgInfo->otpVersion = otpVersion;
247 } else {
248
249 otpVersion = certPkgInfo->otpVersion;
250 //keyIndex = certPkgInfo->keyIndex;
251 activeNvCounterVal = certPkgInfo->activeMinSwVersionVal;
252
253 if ( activeNvCounterVal != swVersion ){
254 CC_PAL_LOG_ERR("active counter version is different from the current\n");
255 return CC_BOOT_IMG_VERIFIER_CERT_SW_VER_ILLEGAL;
256 }
257
258 }
259
260 /* Verify the certificate version against the otp */
261 if (swVersion < otpVersion){
262 CC_PAL_LOG_ERR("currSwVersion1 < minVersion\n");
263 return CC_BOOT_IMG_VERIFIER_SW_VER_SMALLER_THAN_MIN_VER;
264 }
265
266 return CC_OK;
267 }
268
269
270