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