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