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 #include "secureboot_basetypes.h"
12 #include "secureboot_stage_defs.h"
13 #include "secureboot_defs.h"
14 #include "cc_crypto_x509_defs.h"
15 #include "secureboot_base_func.h"
16 #include "bsv_error.h"
17 #include "sb_x509_cert_parser.h"
18 #include "cc3x_sb_x509_ext_parser.h"
19 #include "sb_x509_error.h"
20 #include "bootimagesverifierx509_error.h"
21 #include "util_asn1_parser.h"
22 #include "util_base64.h"
23 #include "util_x509_parser.h"
24 #include "cc_pal_log.h"
25 //#include "bootimagesverifierx509_def.h"
26 #include "bootimagesverifier_def.h"
27 #include "cc_crypto_x509_defs.h"
28
29 /*!
30 * @brief Parse certificate extension segment
31 *
32 * @param[in/out] ppCert - pointer to X509 certificate as ASN.1 byte array
33 * @param[in] certType - certificate type
34 * @param[in] cntNumOfImg - number of images for content certificate (should be 0 for all else)
35 * @param[out] pOutStr - extension data structure according to certificate type
36 * @param[in] pOutStrSize - extension data structure max size
37 * @param[in] maxCertSize - max certficate size
38 * @param[in] startAddress - start address of certificate
39 * @param[in] endAddress - end address of certificate (the certificate pointer cannot exceed this address)
40 *
41 * @return uint32_t - On success: the value CC_OK is returned,
42 * On failure: a value from bsv_error.h
43 */
SB_X509_ParseCertExtensions(uint8_t ** ppCert,uint32_t certSize,CCSbCertHeader_t ** ppCertPropHeader,uint8_t ** ppNp,uint8_t ** ppCertBody,uint32_t * pCertBodySize,unsigned long startAddress,unsigned long endAddress)44 CCError_t SB_X509_ParseCertExtensions(uint8_t **ppCert,
45 uint32_t certSize,
46 CCSbCertHeader_t **ppCertPropHeader,
47 uint8_t **ppNp,
48 uint8_t **ppCertBody,
49 uint32_t *pCertBodySize,
50 unsigned long startAddress,
51 unsigned long endAddress)
52 {
53 CCError_t rc = CC_OK;
54 CCSbCertAsn1Data_t asn1Data;
55 uint32_t nextBuffOffset = 0;
56 uint32_t extNum = 0;
57 uint8_t extVal = 0;
58 uint8_t **ppExtBuff;
59 uint32_t extBuffSize = 0;
60
61
62 /* validate inputs */
63 if ((ppCert == NULL) ||
64 (certSize == 0) ||
65 (ppCertPropHeader == NULL) ||
66 (ppNp == NULL) ||
67 (ppCertBody == NULL) ||
68 (pCertBodySize == NULL)){
69 CC_PAL_LOG_ERR("Invalid inputs\n");
70 return CC_BSV_ILLEGAL_INPUT_PARAM_ERR;
71 }
72
73 /* parse certificate extension header */
74 /* the first tag is always the extension tag */
75 rc = UTIL_Asn1ReadItemVerifyTagFW(ppCert, &asn1Data, CC_X509_CERT_CTX_EXT_TAG_ID, startAddress, endAddress);
76 if (rc != CC_OK) {
77 CC_PAL_LOG_ERR("1. Failed to read CC_X509_CERT_CTX_EXT_TAG_ID \n");
78 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
79 }
80 /* read SEQ */
81 rc = UTIL_Asn1ReadItemVerifyTagFW(ppCert, &asn1Data, CC_X509_CERT_SEQ_TAG_ID, startAddress, endAddress);
82 if (rc != CC_OK) {
83 CC_PAL_LOG_ERR("2. Failed to read CC_X509_CERT_SEQ_TAG_ID \n");
84 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
85 }
86
87 for (extNum=0; extNum < CC3X_X509_CERT_EXT_NUMBER && nextBuffOffset < certSize; extNum++){
88 /* read SEQ */
89 rc = UTIL_Asn1ReadItemVerifyTagFW(ppCert, &asn1Data, CC_X509_CERT_SEQ_TAG_ID, startAddress, endAddress);
90 if (rc != CC_OK) {
91 CC_PAL_LOG_ERR("3. Failed to read CC_X509_CERT_SEQ_TAG_ID\n");
92 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
93 }
94 nextBuffOffset += asn1Data.itemSize;
95 /* read OBJ ID */
96 rc = UTIL_Asn1ReadItemVerifyTagFW(ppCert, &asn1Data, CC_X509_CERT_OBJ_IDENTIFIER_TAG_ID, startAddress, endAddress);
97 if (rc != CC_OK) {
98 CC_PAL_LOG_ERR("3. Failed to read CC_X509_CERT_SEQ_TAG_ID\n");
99 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
100 }
101 /* the last byte of the identifier , identifies the extension field */
102 if (asn1Data.itemSize == 0){
103 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
104 }
105 extVal = *((*ppCert) + asn1Data.itemSize -1);
106 UTIL_ASN1_GET_NEXT_ITEM_RET(*ppCert, asn1Data.itemSize, startAddress, endAddress);
107
108 rc = UTIL_Asn1ReadItemVerifyTagFW(ppCert, &asn1Data, CC_X509_CERT_BOOL_TAG_ID, startAddress, endAddress);
109 if (rc != CC_OK) {
110 CC_PAL_LOG_ERR("5. Failed to read CC_X509_CERT_BOOL_TAG_ID\n");
111 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
112 }
113 UTIL_ASN1_GET_NEXT_ITEM_RET(*ppCert, asn1Data.itemSize, startAddress, endAddress);
114
115 switch(extNum) {
116 case 0:
117 if (extVal != CC_X509_ID_EXT_PROPRIETARY_HEADER) {
118 CC_PAL_LOG_ERR("Illegal extension %d, expected Header\n", extVal);
119 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
120 }
121
122 ppExtBuff = (uint8_t **)ppCertPropHeader;
123 extBuffSize = sizeof(CCSbCertHeader_t);
124 break;
125 case 1:
126 if (extVal != CC_X509_ID_EXT_PUB_KEY_NP) {
127 CC_PAL_LOG_ERR("Illegal extension %d, expected Np\n", extVal);
128 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
129 }
130 ppExtBuff = (uint8_t **)ppNp;
131 extBuffSize = RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES;
132 break;
133 case 2:
134 if ((extVal != CC_X509_ID_EXT_KEY_CERT_MAIN_VAL) &&
135 (extVal != CC_X509_ID_EXT_CONTENT_CERT_MAIN_VAL) &&
136 (extVal != CC_X509_ID_EXT_ENABLER_CERT_MAIN_VAL) &&
137 (extVal != CC_X509_ID_EXT_DEVELOPER_CERT_MAIN_VAL)) {
138 CC_PAL_LOG_ERR("Illegal extension %d, expected key, content, enabler, developer\n", extVal);
139 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
140 }
141 ppExtBuff = (uint8_t **)ppCertBody;
142 extBuffSize = *pCertBodySize;
143 break;
144 default:
145 CC_PAL_LOG_ERR("Invalid loop %d\n", extNum);
146 return CC_SB_X509_CERT_PARSE_ILLEGAL_VAL;
147 }
148
149 rc = UTIL_Asn1ReadItemVerifyTagFW(ppCert, &asn1Data, CC_X509_CERT_OCT_STR_TAG_ID, startAddress, endAddress);
150 if (rc != CC_OK) {
151 CC_PAL_LOG_ERR("Failed to verify CC_X509_CERT_OCT_STR_TAG_ID, rc 0x%X\n", rc);
152 return rc;
153 }
154 /* in case we have leading 0 before buffer */
155 if ((asn1Data.itemSize > extBuffSize) && (**ppCert == 0)) {
156 UTIL_ASN1_GET_NEXT_ITEM_RET(*ppCert, 1, startAddress, endAddress);
157 asn1Data.itemSize--;
158 } else if (asn1Data.itemSize > extBuffSize) {
159 CC_PAL_LOG_ERR("Invalid inputs > extBuffSize 0x%x\n", extBuffSize);
160 return CC_BSV_ILLEGAL_INPUT_PARAM_ERR;
161 }
162
163 *ppExtBuff = (uint8_t*)*ppCert;
164 if (extNum == 2) {
165 *pCertBodySize = asn1Data.itemSize;
166 }
167
168 UTIL_ASN1_GET_NEXT_ITEM_RET(*ppCert, asn1Data.itemSize, startAddress, endAddress);
169 }
170
171 return CC_OK;
172 }
173
174