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