1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "secureboot_basetypes.h"
8 #include "secureboot_general_hwdefs.h"
9 #include "bsv_defs.h"
10 #include "bsv_error.h"
11 #include "cc_pal_log.h"
12 #include "cc_otp_defs.h"
13 #include "bootimagesverifier_def.h"
14 #include "secureboot_stage_defs.h"
15 #include "secureboot_base_func.h"
16 #include "secureboot_base_swimgverify.h"
17 #include "bootimagesverifier_swcomp.h"
18 #include "bootimagesverifier_error.h"
19 #include "bootimagesverifier_parser.h"
20 #include "common_cert_parser.h"
21 #include "cc_crypto_boot_defs.h"
22 #include "nvm.h"
23 #include "secdebug_api.h"
24 #include "secdebug_defs.h"
25 
26 const uint32_t certMagicNumber[CC_SB_MAX_CERT] = {
27         /* No enum */           0,
28         /*  CC_SB_KEY_CERT       */ CC_SB_KEY_CERT_MAGIC_NUMBER,
29         /*  CC_SB_CONTENT_CERT   */ CC_SB_CONTENT_CERT_MAGIC_NUMBER,
30         0,
31         /*  CC_SB_ENABLER_CERT   */ CC_CERT_SEC_DEBUG_ENABLER_MAGIC,
32         /*  CC_SB_DEVELOPER_CERT */ CC_CERT_SEC_DEBUG_DEVELOPER_MAGIC
33 };
34 
35 const uint32_t certMainMaxSize[CC_SB_MAX_CERT] = {
36         /* No enum */                 0,
37         /*  CC_SB_KEY_CERT       */(CC_SB_MAX_KEY_CERT_SIZE_IN_BYTES - CC_SB_MAX_CERT_SIGN_SIZE_IN_BYTES),
38         /*  CC_SB_CONTENT_CERT   */(CC_SB_MAX_CONTENT_CERT_SIZE_IN_BYTES - CC_SB_MAX_CERT_SIGN_SIZE_IN_BYTES),
39         0,
40         /*  CC_SB_ENABLER_CERT   */(CC_SB_MAX_ENABLER_CERT_SIZE_IN_BYTES - CC_SB_MAX_CERT_SIGN_SIZE_IN_BYTES),
41         /*  CC_SB_DEVELOPER_CERT */(CC_SB_MAX_DEVELOPER_CERT_SIZE_IN_BYTES - CC_SB_MAX_CERT_SIGN_SIZE_IN_BYTES)
42 };
43 
44 
45 uint32_t hbkId2HashSizeWords[] = {
46         /* CC_SB_HASH_BOOT_KEY_0_128B */  CC_BSV_128B_HASH_SIZE_IN_WORDS,
47         /* CC_SB_HASH_BOOT_KEY_1_128B */  CC_BSV_128B_HASH_SIZE_IN_WORDS,
48         /* CC_SB_HASH_BOOT_KEY_256B   */ CC_BSV_256B_HASH_SIZE_IN_WORDS,
49 };
50 
51 
52 
53 
verifyCertPubKeyAndSign(unsigned long hwBaseAddress,uint32_t * pCert,size_t certSize,CCSbCertInfo_t * pSbCertInfo,workspaceInt_t * pWorkspaceInt)54 static CCError_t verifyCertPubKeyAndSign(unsigned long hwBaseAddress,
55                                          uint32_t    *pCert,
56                                          size_t      certSize,
57                                          CCSbCertInfo_t  *pSbCertInfo,
58                                          workspaceInt_t  *pWorkspaceInt)
59 {
60         CCError_t rc = CC_OK;
61         uint32_t  expPubKeyHashSizeWords;
62         CCHashResult_t    expPubKeyHash;
63 
64         if (pSbCertInfo->initDataFlag != CC_SB_FIRST_CERT_IN_CHAIN) { // not first certificate in chain
65                 expPubKeyHashSizeWords = sizeof(CCHashResult_t) / CC_32BIT_WORD_SIZE;
66                 UTIL_MemCopy((uint8_t *)expPubKeyHash, (uint8_t *)pSbCertInfo->pubKeyHash, expPubKeyHashSizeWords * CC_32BIT_WORD_SIZE);
67         } else { // meaning this is first certificate in chain
68                 expPubKeyHashSizeWords = hbkId2HashSizeWords[pSbCertInfo->keyIndex];
69                 rc = NVM_ReadHASHPubKey(hwBaseAddress,
70                                         pSbCertInfo->keyIndex,
71                                         expPubKeyHash,
72                                         expPubKeyHashSizeWords);
73                 if (rc != CC_OK) {
74                         // if HBK not programed yet, skip HBK verify, but continue verifying the certificate
75                         if (rc == CC_BOOT_IMG_VERIFIER_SKIP_PUBLIC_KEY_VERIFY) {
76                                 expPubKeyHashSizeWords = 0;
77                         } else {
78                                 CC_PAL_LOG_ERR("Failed NVM_ReadHASHPubKey 0x%x", rc);
79                                 return rc;
80                         }
81                 }
82         }
83 
84         /* Verify  public key hash only if expectedSize > 0 */
85         if (expPubKeyHashSizeWords > 0) {
86                 rc = CCSbCalcPublicKeyHASHAndCompare(hwBaseAddress,
87                                                      (uint32_t *)(&pWorkspaceInt->pubKey.N[0]),
88                                                      expPubKeyHash,
89                                                      expPubKeyHashSizeWords * CC_32BIT_WORD_SIZE);
90                 if (rc != CC_OK) {
91                         CC_PAL_LOG_ERR("CCSbCalcPublicKeyHASHAndCompare failed 0x%x\n", rc);
92                         return rc;
93                 }
94         }
95 
96         /* Verify the certificate signature */
97         rc = CCSbVerifySignature(hwBaseAddress,
98                                  pCert,
99                                  (CCSbNParams_t *)(pWorkspaceInt->pubKey.N),
100                                  (CCSbSignature_t *)&pWorkspaceInt->signature,
101                                  certSize,
102                                  RSA_PSS_3072);
103         if (rc != CC_OK) {
104                 CC_PAL_LOG_ERR("CCSbVerifySignature failed 0x%x\n", rc);
105                 return rc;
106         }
107 
108         return CC_OK;
109 
110 }
111 
112 /* The function validates the certificate header - Magic number , type and version. */
CCCertValidateHeader(CCSbCertHeader_t * pCertHeader,CCSbCertTypes_t * pCertType)113 static CCError_t CCCertValidateHeader(CCSbCertHeader_t *pCertHeader,
114                                       CCSbCertTypes_t *pCertType)
115 {
116         uint32_t expVersion;
117         CCSbCertTypes_t certType = CC_SB_MAX_CERT;
118         uint32_t i = 0;
119 
120         /* Verify Magic number, and get certificate type out of it */
121         /*---------------------*/
122         if (pCertHeader->magicNumber == 0) {
123                 CC_PAL_LOG_ERR("certificate magic number is incorrect \n");
124                 return CC_BOOT_IMG_VERIFIER_INCORRECT_CERT_TYPE;
125         }
126 
127         for (i = CC_SB_MIN_CERT + 1; i < CC_SB_MAX_CERT; i++) {
128                 if (pCertHeader->magicNumber == certMagicNumber[i]) {
129                         certType = (CCSbCertTypes_t)i;
130                         break;
131                 }
132         }
133 
134         if ((certType & *pCertType) == 0) {
135                 CC_PAL_LOG_ERR("certificate type is incorrect %d exp 0x%x\n", certType, *pCertType);
136                 return CC_BOOT_IMG_VERIFIER_INCORRECT_CERT_TYPE;
137         }
138 
139         /* Verify certificate version */
140         /*----------------------------*/
141         expVersion = (CC_SB_CERT_VERSION_MAJOR << CERT_VERSION_MAJOR_BIT_SHIFT) | CC_SB_CERT_VERSION_MINOR;
142         if (pCertHeader->certVersion != expVersion) {
143                 CC_PAL_LOG_ERR("Certificate version incorrect, expVersion 0x%x, pCertHeader->certVersion 0x%x\n",
144                                expVersion, pCertHeader->certVersion);
145                 return CC_BOOT_IMG_VERIFIER_CERT_VERSION_NUM_INCORRECT;
146         }
147 
148         // set the actual certificate type
149         *pCertType = certType;
150         return CC_OK;
151 
152 }
153 
154 
155 
156 /**
157    @brief This function is basic verification for all secure boot/debug certificates.
158    it verifies type, size, public key and signature.
159    Return pointers to certificate proprietary header, and body.
160    Workspace should be clear when function returns
161         call CCCertFieldsParse() - according to certificate type(x509 or not),
162                 copy public key, Np and signature to workspace,
163                 and returns pointers to certificate proprietary header, and body.
164         call CCCertValidateHeader(), and verify cert type (as expected) and size (according to type).
165         If expected public key hash is NULL, call CC_BsvPubKeyHashGet() with HBK type defined in certificate to get OTP HBK
166         Call verifyCertPubKeyAndSign() To verify public key and certificate signature.
167                 Public key is verified against the expected value, and N and Np and signature resides on workspace.
168 
169  */
CCCommonCertVerify(unsigned long hwBaseAddress,BufferInfo32_t * pCertInfo,CertFieldsInfo_t * pCertFields,CCSbCertInfo_t * pSbCertInfo,BufferInfo32_t * pWorkspaceInfo,BufferInfo32_t * pX509HeaderInfo)170 CCError_t CCCommonCertVerify(unsigned long   hwBaseAddress,
171                              BufferInfo32_t  *pCertInfo,
172                              CertFieldsInfo_t  *pCertFields,  // in/out
173                              CCSbCertInfo_t  *pSbCertInfo,   //in/out
174                              BufferInfo32_t  *pWorkspaceInfo,
175                              BufferInfo32_t  *pX509HeaderInfo) //in/out
176 {
177         uint32_t        rc = 0;
178         uint32_t        certSignedSize = 0;
179         keyCertFlags_t  certFlag;
180         uint32_t    *pCertStartSign;
181 
182         if ((pWorkspaceInfo == NULL) ||
183             (pWorkspaceInfo->pBuffer == NULL) ||
184             (pWorkspaceInfo->bufferSize < sizeof(workspaceInt_t)) ||
185             (!IS_ALIGNED(pWorkspaceInfo->bufferSize, sizeof(uint32_t))) ||
186             (!IS_ALIGNED(sizeof(workspaceInt_t), sizeof(uint32_t)))) {
187                 CC_PAL_LOG_ERR("workspace and or sizes illegal\n");
188                 return CC_BSV_ILLEGAL_INPUT_PARAM_ERR;
189         }
190 
191         /* Parse the certificate fields to get pointers to the certificate internals */
192         /*---------------------------------------------------------------------------*/
193         rc = CCCertFieldsParse(pCertInfo,
194                                pWorkspaceInfo,
195                                pCertFields,
196                                &pCertStartSign,
197                                &certSignedSize,
198                                pX509HeaderInfo);
199         if (rc != CC_OK) {
200                 CC_PAL_LOG_ERR("Failed CCCertFieldsParse 0x%x\n", rc);
201                 goto end_with_error;
202         }
203         /* Verify Magic number, and version. returns the certificate type */
204         /*----------------------------------------------------------------*/
205         rc = CCCertValidateHeader(&pCertFields->certHeader, &pCertFields->certType);
206         if (rc != CC_OK) {
207                 CC_PAL_LOG_ERR("Failed CCCertValidateHeader 0x%x\n", rc);
208                 goto end_with_error;
209         }
210 
211         // Verify certificate size. no need to verify the type again
212         if (((pCertFields->certType == CC_SB_KEY_CERT) ||
213              (pCertFields->certType == CC_SB_CONTENT_CERT) ||
214              (pCertFields->certType == CC_SB_ENABLER_CERT) ||
215              (pCertFields->certType ==  CC_SB_DEVELOPER_CERT)) &&
216             (certSignedSize > certMainMaxSize[pCertFields->certType])) {
217                 CC_PAL_LOG_ERR("certSignedSize too big 0x%x for cert %d\n", certSignedSize, pCertFields->certType);
218                 rc = CC_BOOT_IMG_VERIFIER_INCORRECT_CERT_TYPE;
219                 goto end_with_error;
220         }
221 
222         if (pSbCertInfo->initDataFlag == CC_SB_FIRST_CERT_IN_CHAIN) { // Verify the first HBK in chain
223                 certFlag.flagsWord = pCertFields->certHeader.certFlags;
224                 pSbCertInfo->keyIndex = (CCSbPubKeyIndexType_t)(certFlag.flagsBits.hbkId);
225                 if (pSbCertInfo->keyIndex > CC_SB_HASH_BOOT_KEY_256B) {
226                         CC_PAL_LOG_ERR("invalid hbkId %d", pSbCertInfo->keyIndex);
227                         rc = CC_BOOT_IMG_VERIFIER_ILLEGAL_HBK_IDX;
228                         goto end_with_error;
229                 }
230         }
231 
232 
233         /* Verify certificate public key and it's signature,  pCertStartSign is word aligned for propritery and x509*/
234         /*--------------------------------------------------*/
235         rc = verifyCertPubKeyAndSign(hwBaseAddress,
236                                      (uint32_t *)pCertStartSign,
237                                      certSignedSize,
238                                      pSbCertInfo,
239                                      (workspaceInt_t  *)pWorkspaceInfo->pBuffer);
240         if (rc != CC_OK) {
241                 CC_PAL_LOG_ERR("verifyCertPubKeyAndSign failed 0x%X\n", rc);
242                 goto end_with_error;
243         }
244 
245         goto end;
246 
247 end_with_error:
248         UTIL_MemSet((uint8_t *)pCertFields, 0, sizeof(CertFieldsInfo_t));
249 end:
250         UTIL_MemSet((uint8_t *)pWorkspaceInfo->pBuffer, 0, pWorkspaceInfo->bufferSize);
251         return rc;
252 }
253 
254 
255 /**
256    @brief This function verifies key certificate specific fields
257         The header flags, NV counter according to HBK type
258         Return next certificate public key hash.
259  */
CCCommonKeyCertVerify(unsigned long hwBaseAddress,uint32_t certFlags,uint8_t * pCertMain,CCSbCertInfo_t * pCertPkgInfo)260 uint32_t CCCommonKeyCertVerify(unsigned long   hwBaseAddress,
261                                uint32_t certFlags,
262                                uint8_t *pCertMain,
263                                CCSbCertInfo_t *pCertPkgInfo)
264 {
265         uint32_t       rc = 0;
266         keyCertFlags_t  keyFlag;
267         KeyCertMain_t certMain;
268 
269         keyFlag.flagsWord = certFlags;
270 
271         if (pCertPkgInfo->initDataFlag == CC_SB_FIRST_CERT_IN_CHAIN) {
272                 pCertPkgInfo->keyIndex = (CCSbPubKeyIndexType_t)(keyFlag.flagsBits.hbkId);
273         }
274 
275         /* Copy non-aligned certFields.pCertBody into aligned struct */
276         UTIL_MemCopy((uint8_t *)&certMain, (uint8_t *)pCertMain, sizeof(KeyCertMain_t));
277 
278         /* Verify that the SW version is valid */
279         rc = CCSbVerifyNvCounter(hwBaseAddress, certMain.swVer, pCertPkgInfo);
280         if (rc != CC_OK) {
281                 CC_PAL_LOG_ERR("CCSbVerifyNvCounter failed 0x%X\n", rc);
282                 return rc;
283         }
284         if (pCertPkgInfo->initDataFlag == CC_SB_FIRST_CERT_IN_CHAIN) {
285                 pCertPkgInfo->activeMinSwVersionVal = certMain.swVer;
286         }
287 
288         /* Set function output values */
289         UTIL_MemCopy((uint8_t *)pCertPkgInfo->pubKeyHash, (uint8_t *)certMain.nextPubKeyHash, sizeof(CCHashResult_t));
290 
291         return CC_OK;
292 }
293 
294 /**
295    @brief This function   verifies content certificate specific fields
296         Verifies certificate flags, NV counter according to HBK type
297         Call CCCertValidateSWComps()
298         Call CCSbSetNvCounter()
299  *      The function uses the workspace  for loading the
300  *      non-signed certificate part and  if required to load and
301  *      verify the images.
302  */
CCCommonContentCertVerify(CCSbFlashReadFunc flashReadFunc,void * userContext,unsigned long hwBaseAddress,CCAddr_t certStoreAddress,CCSbCertInfo_t * certPkgInfo,uint32_t certFlags,uint8_t * pCertMain,BufferInfo32_t * pWorkspaceInfo)303 uint32_t CCCommonContentCertVerify(CCSbFlashReadFunc flashReadFunc,
304                                    void *userContext,
305                                    unsigned long hwBaseAddress,
306                                    CCAddr_t certStoreAddress,
307                                    CCSbCertInfo_t *certPkgInfo,
308                                    uint32_t certFlags,
309                                    uint8_t  *pCertMain,
310                                    BufferInfo32_t  *pWorkspaceInfo)
311 {
312         CCError_t rc = CC_OK;
313         CCSbCertParserSwCompsInfo_t swImagesData;
314         /* Content additional data is always word aligned*/
315         uint32_t *pSwImagesAddData;
316         uint32_t sizeOfNonSignedCert = 0;
317         uint32_t numOfImages = 0;
318         CCSbCertFlags_t flags;
319         uint32_t  swVer;
320 
321 
322         /* 1. Get the number of sw components from the header flags field */
323         flags.flagsWord = certFlags;
324         numOfImages = flags.flagsBits.numOfSwCmp;
325         if ((numOfImages > CC_SB_MAX_NUM_OF_IMAGES) ||
326             (numOfImages == 0)) {
327                 return CC_BOOT_IMG_VERIFIER_ILLEGAL_NUM_OF_IMAGES;
328         }
329 
330         /* 2. Load the extended data (unsigned data), in this stage the certificate is already verified. */
331         sizeOfNonSignedCert = numOfImages * SW_REC_NONE_SIGNED_DATA_SIZE_IN_BYTES;
332         if (sizeOfNonSignedCert > pWorkspaceInfo->bufferSize) {
333                 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
334         }
335 
336         /* Read the Non-signed part of the certificate package from the Flash, and place it right after the certificate. */
337         rc = flashReadFunc(certStoreAddress, (uint8_t *)pWorkspaceInfo->pBuffer, sizeOfNonSignedCert, userContext);
338         if (rc != CC_OK) {
339                 CC_PAL_LOG_ERR("failed flashRead_func for Non-signed part\n");
340                 return rc;
341         }
342         pSwImagesAddData = pWorkspaceInfo->pBuffer;
343         pWorkspaceInfo->bufferSize -= sizeOfNonSignedCert;
344         pWorkspaceInfo->pBuffer += (sizeOfNonSignedCert / CC_32BIT_WORD_SIZE) + 1;
345 
346         /* 3. verify sw version
347            Copy 4 bytes instead of accessing teh struct field, since  pCertMain is not word aligned */
348         UTIL_MemCopy((uint8_t *)&swVer, (uint8_t *)pCertMain, sizeof(uint32_t));
349         rc = CCSbVerifyNvCounter(hwBaseAddress, swVer, certPkgInfo);
350         if (rc != CC_OK) {
351                 CC_PAL_LOG_ERR("CCSbVerifyNvCounter failed\n");
352                 return rc;
353         }
354 
355         /* 4. load and verify sw comps */
356         swImagesData.swCodeEncType = (CCswCodeEncType_t)(flags.flagsBits.swCodeEncType);
357         swImagesData.swLoadVerifyScheme = (CCswLoadVerifyScheme_t)(flags.flagsBits.swLoadVerifyScheme);
358         swImagesData.swCryptoType = (CCswCryptoType_t)(flags.flagsBits.swCryptoType);
359         swImagesData.numOfSwComps = (flags.flagsBits.numOfSwCmp);
360 
361         /* move the pointers for nonce and images by sizeof bytes instead of using struct fiels, since  pCertMain is not word aligned */
362         UTIL_MemCopy((uint8_t *)swImagesData.nonce, (uint8_t *)(((unsigned long)pCertMain) + sizeof(uint32_t)), sizeof(CCSbNonce_t));
363         swImagesData.pSwCompsData = (uint8_t *)(((unsigned long)pCertMain) + sizeof(uint32_t) + sizeof(CCSbNonce_t));
364 
365         rc = CCCertValidateSWComps(flashReadFunc,
366                                    userContext,
367                                    hwBaseAddress,
368                                    certPkgInfo->keyIndex,
369                                    &swImagesData,
370                                    pSwImagesAddData,
371                                    pWorkspaceInfo->pBuffer,
372                                    pWorkspaceInfo->bufferSize);
373         if (rc != CC_OK) {
374                 CC_PAL_LOG_ERR("CCCertValidateSWComps failed\n");
375                 return rc;
376         }
377 
378         /* 5. Assuming there is only one content certificate in the chain, */
379         /*    Set the sw version in the OTP (if required)  */
380         rc = CCSbSetNvCounter(hwBaseAddress, certPkgInfo);
381         if (rc != CC_OK) {
382                 CC_PAL_LOG_ERR("CCSbSetNvCounter failed\n");
383                 return rc;
384         }
385         return CC_OK;
386 }
387 
388 
389