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 #include "secureboot_basetypes.h"
11 #include "secureboot_error.h"
12 #include "bootimagesverifier_error.h"
13 #include "bootimagesverifier_def.h"
14 #include "bootimagesverifier_parser.h"
15 #include "secureboot_base_func.h"
16 #include "secureboot_base_swimgverify.h"
17 #include "cc_pal_log.h"
18 #include "secureboot_defs.h"
19 #include "bootimagesverifier_swcomp.h"
20 #include "common_cert_verify.h"
21 #include "common_cert_parser.h"
22 
23 /************************ Defines ******************************/
24 
25 
26 /************************ Enums ******************************/
27 
28 
29 /************************ Typedefs ******************************/
30 
31 
32 /************************ Global Data ******************************/
33 
34 /************************ Private functions  ******************************/
35 
36 /************************ Public functions  ******************************/
37 
CC_SbCertChainVerificationInit(CCSbCertInfo_t * certPkgInfo)38 CCError_t CC_SbCertChainVerificationInit(CCSbCertInfo_t *certPkgInfo)
39 {
40         if (certPkgInfo == NULL) {
41                 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
42         }
43         /*clear the external hash */
44         UTIL_MemSet((uint8_t *)&(certPkgInfo->pubKeyHash), 0x0, sizeof(certPkgInfo->pubKeyHash));
45         certPkgInfo->initDataFlag = 0;
46 
47 
48         return CC_OK;
49 }
50 
51 
52 /**
53    @brief This function
54    loadSbCert() loads the certificate from Flash to RAM
55         if called first time, expected certificate is key certificate
56         else, if second time, expected is key or content certificate
57         else, if third, expected is content.
58    Call CCCommonCertVerify(expected types) to verify common certificate fields,
59         and returns pointers to certificate proprietary header, and body.
60    If certificate type in proprietary header is key, call CCCommonKeyCertVerify(), to verify key certificate fields.
61    Otherwise, call CCCommonContentCertVerify(), to verify Content certificate fields.
62 */
CC_SbCertVerifySingle(CCSbFlashReadFunc flashReadFunc,void * userContext,unsigned long hwBaseAddress,CCAddr_t certStoreAddress,CCSbCertInfo_t * pCertPkgInfo,uint32_t * pHeader,uint32_t headerSize,uint32_t * pWorkspace,uint32_t workspaceSize)63 CCError_t CC_SbCertVerifySingle(CCSbFlashReadFunc flashReadFunc,
64                                 void *userContext,
65                                 unsigned long hwBaseAddress,
66                                 CCAddr_t certStoreAddress,
67                                 CCSbCertInfo_t *pCertPkgInfo,
68                                 uint32_t *pHeader,     // used for X509 header
69                                 uint32_t  headerSize,
70                                 uint32_t *pWorkspace,
71                                 uint32_t workspaceSize)
72 {
73         CCError_t   rc = CC_OK;
74         uint32_t    certLoadWordSize;
75         CertFieldsInfo_t  certFields;
76         BufferInfo32_t  workspaceInfo;
77         BufferInfo32_t  certInfo;
78         BufferInfo32_t  x509HeaderInfo;
79         BufferInfo32_t *pX509HeaderInfo = NULL;
80 
81 
82         /* 1. Verify input parameters */
83         /*----------------------------*/
84         if ((flashReadFunc == NULL) ||
85             (pCertPkgInfo == NULL) ||
86             (pWorkspace == NULL) ||
87             (workspaceSize == 0) ||
88             ((unsigned long)pWorkspace + workspaceSize < (unsigned long)pWorkspace) ||   /* Verify no overflow in workspace */
89             (workspaceSize < CC_SB_MIN_WORKSPACE_SIZE_IN_BYTES) ||
90             (!IS_ALIGNED(workspaceSize, sizeof(uint32_t))) ||
91             (!IS_ALIGNED(pWorkspace, sizeof(uint32_t)))) {
92                 CC_PAL_LOG_ERR("illegal params \n");
93                 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
94         }
95         if ((pHeader != NULL) && (headerSize != 0)) {
96                 x509HeaderInfo.pBuffer = pHeader;
97                 x509HeaderInfo.bufferSize = headerSize;
98                 pX509HeaderInfo = &x509HeaderInfo;
99         }
100 
101         if (CC_SB_MAX_CERT_SIZE_IN_BYTES < CC_SB_MAX_CONTENT_PKG_SIZE_IN_BYTES) {
102                 CC_PAL_LOG_ERR("CC_SB_MAX_CERT_SIZE_IN_BYTES \n");
103                 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
104         }
105 
106         UTIL_MemSet((uint8_t *)&certFields, 0, sizeof(CertFieldsInfo_t));
107         /* Clearing the RAM just to verify that there is no secret data on it, before starting to process certificate */
108         UTIL_MemSet((uint8_t *)pWorkspace, 0, workspaceSize);
109 
110 
111         /* 2. Load the certificate from the Flash */
112         /*----------------------------------------*/
113         /* Set the maximum certificate size, and get back the current certificate size.
114            The certificate to load is 32 bit aligned */
115         certLoadWordSize = (CC_SB_MAX_CERT_SIZE_IN_BYTES / CC_32BIT_WORD_SIZE);
116         rc = CCCertLoadCertificate(flashReadFunc,
117                                    userContext,
118                                    certStoreAddress,
119                                    pWorkspace,
120                                    &certLoadWordSize);
121         if (rc != CC_OK) {
122                 CC_PAL_LOG_ERR("CCCertParserLoadCertificate  returned 0x%X\n", (unsigned int)rc);
123                 return rc;
124         }
125 
126         /* workspace order:
127            [0]  certificate
128             [certificate size]   if content certificate - additional data for images and addresses
129            [end of workspace]   N+Np+Signature  OR images information */
130         certInfo.pBuffer =  pWorkspace;
131 
132         /* Set expected certificate type according to the certificate place in chain - first key ,
133            second key or content, third content. Maximal size in content certificate is calculated according to
134            MAX number of possible SW images.*/
135         switch (pCertPkgInfo->initDataFlag) {
136         case CC_SB_FIRST_CERT_IN_CHAIN:
137                 certFields.certType = CC_SB_KEY_CERT;
138                 certFields.certBodySize = sizeof(KeyCertMain_t);
139                 certInfo.bufferSize = CC_SB_MAX_KEY_CERT_SIZE_IN_BYTES;
140                 break;
141         case CC_SB_SECOND_CERT_IN_CHAIN:
142                 certFields.certType = CC_SB_KEY_OR_CONTENT_CERT;
143                 certFields.certBodySize = sizeof(ContentCertMain_t);
144                 certInfo.bufferSize = CC_SB_MAX_CONTENT_CERT_SIZE_IN_BYTES;
145                 break;
146         case CC_SB_THIRD_CERT_IN_CHAIN:
147                 certFields.certType = CC_SB_CONTENT_CERT;
148                 certFields.certBodySize = sizeof(ContentCertMain_t);
149                 certInfo.bufferSize = CC_SB_MAX_CONTENT_CERT_SIZE_IN_BYTES;
150                 break;
151         default:
152                 CC_PAL_LOG_ERR("Not expecting any certificate in the chain \n");
153                 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
154         }
155 
156         // set the workspace for N, Np and signature
157         workspaceInfo.bufferSize = sizeof(workspaceInt_t);
158         workspaceInfo.pBuffer = (uint32_t *)((unsigned long)pWorkspace + workspaceSize - sizeof(workspaceInt_t));
159 
160         /* 3. Verify the certificate (Verify the RSA signature and the public key hash) . */
161         rc = CCCommonCertVerify(hwBaseAddress,
162                                 &certInfo,
163                                 &certFields,
164                                 pCertPkgInfo,
165                                 &workspaceInfo,
166                                 pX509HeaderInfo);
167         if (rc != CC_OK) {
168                 CC_PAL_LOG_ERR("CCCommonCertVerify failed 0x%X\n", rc);
169                 return rc;
170         }
171 
172 
173         /* 4. In case of content certificate - verify the SW images */
174         /*----------------------------------------------------------*/
175         switch (certFields.certType) {
176         case CC_SB_KEY_CERT:
177                 /* Verify the key certificate sw version. */
178                 rc = CCCommonKeyCertVerify(hwBaseAddress,
179                                            certFields.certHeader.certFlags,
180                                            certFields.pCertBody,
181                                            pCertPkgInfo);
182                 /* Update the certificate number in the chain.*/
183                 pCertPkgInfo->initDataFlag++;
184                 break;
185         case CC_SB_CONTENT_CERT:
186                 /* Verify the content certificate sw version and verify the SW images. If needed update the sw version.
187                   workspaceInfo may overlap with N+Np+Signature, since N, Np and signature were already verified */
188                 workspaceInfo.pBuffer = pWorkspace + certLoadWordSize;
189                 workspaceInfo.bufferSize = workspaceSize - certLoadWordSize * CC_32BIT_WORD_SIZE;
190                 rc = CCCommonContentCertVerify(flashReadFunc,
191                                                userContext,
192                                                hwBaseAddress,
193                                                certStoreAddress + certLoadWordSize * CC_32BIT_WORD_SIZE,
194                                                pCertPkgInfo,
195                                                certFields.certHeader.certFlags,
196                                                certFields.pCertBody,
197                                                &workspaceInfo);
198                 /* the content certificate is always the last. */
199                 pCertPkgInfo->initDataFlag = CC_SB_LAST_CERT_IN_CHAIN;
200                 break;
201         default:
202                 CC_PAL_LOG_ERR("Illegal certificate type for secure boot flow.\n");
203                 return CC_BOOT_IMG_VERIFIER_INV_INPUT_PARAM;
204         }
205 
206         return rc;
207 
208 } /* End of CC_SbCertVerifySingle */
209 
210 
211 
212