1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15 #include "hitls_build.h"
16 #ifdef HITLS_TLS_HOST_SERVER
17 #include "securec.h"
18 #include "tls_binlog_id.h"
19 #include "bsl_log_internal.h"
20 #include "bsl_log.h"
21 #include "bsl_sal.h"
22 #include "bsl_err_internal.h"
23 #include "bsl_bytes.h"
24 #include "hitls_error.h"
25 #include "hitls_config.h"
26 #include "hs_msg.h"
27 #include "hs.h"
28 #include "parse_common.h"
29 #include "parse_extensions.h"
30 #include "parse_msg.h"
31
32
33 #define SINGLE_CIPHER_SUITE_SIZE 2u /* Length of the signature cipher suite */
34 #ifdef HITLS_TLS_CONNECTION_INFO_NEGOTIATION
StoreClientCipherSuites(TLS_Ctx * ctx,ClientHelloMsg * msg)35 static int32_t StoreClientCipherSuites(TLS_Ctx *ctx, ClientHelloMsg *msg)
36 {
37 uint32_t scsvCount = 0;
38 scsvCount += msg->haveEmptyRenegoScsvCipher ? 1 : 0;
39 scsvCount += msg->haveFallBackScsvCipher ? 1 : 0;
40 if (scsvCount == msg->cipherSuitesSize) {
41 BSL_SAL_FREE(ctx->peerInfo.cipherSuites);
42 ctx->peerInfo.cipherSuitesSize = 0;
43 return HITLS_SUCCESS;
44 }
45 uint32_t tmpSize = 0;
46 BSL_SAL_FREE(ctx->peerInfo.cipherSuites);
47 uint32_t peerCipherSuitesSize = ((uint32_t)msg->cipherSuitesSize - scsvCount) * sizeof(uint16_t);
48 ctx->peerInfo.cipherSuites = (uint16_t *)BSL_SAL_Malloc(peerCipherSuitesSize);
49 if (ctx->peerInfo.cipherSuites == NULL) {
50 BSL_SAL_FREE(msg->cipherSuites);
51 ctx->peerInfo.cipherSuitesSize = 0;
52 return ParseErrorProcess(ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID16237,
53 BINGLOG_STR("peer cipherSuites dump fail"), ALERT_UNKNOWN);
54 }
55 for (uint16_t index = 0u; index < msg->cipherSuitesSize; index++) {
56 if (msg->cipherSuites[index] == TLS_EMPTY_RENEGOTIATION_INFO_SCSV ||
57 msg->cipherSuites[index] == TLS_FALLBACK_SCSV) {
58 continue;
59 }
60 ctx->peerInfo.cipherSuites[tmpSize] = msg->cipherSuites[index];
61 tmpSize += 1;
62 }
63 ctx->peerInfo.cipherSuitesSize = (uint16_t)tmpSize;
64 return HITLS_SUCCESS;
65 }
66 #endif
67
68 /**
69 * @brief Parse the cipher suite list of Client Hello messages.
70 *
71 * @param pkt [IN] parse context
72 * @param msg [OUT] Client Hello Structure
73 *
74 * @retval HITLS_SUCCESS parsed successfully.
75 * @retval HITLS_MEMALLOC_FAIL Memory application failed.
76 * @retval HITLS_PARSE_INVALID_MSG_LEN The message length is incorrect.
77 */
ParseClientHelloCipherSuites(ParsePacket * pkt,ClientHelloMsg * msg)78 static int32_t ParseClientHelloCipherSuites(ParsePacket *pkt, ClientHelloMsg *msg)
79 {
80 uint16_t cipherSuitesLen = 0;
81 int32_t ret = ParseBytesToUint16(pkt, &cipherSuitesLen);
82 const char *logStr = BINGLOG_STR("parse cipherSuites failed.");
83 if (ret != HITLS_SUCCESS) {
84 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15700,
85 logStr, ALERT_DECODE_ERROR);
86 }
87 if (((uint32_t)cipherSuitesLen > (pkt->bufLen - *pkt->bufOffset)) ||
88 (cipherSuitesLen % SINGLE_CIPHER_SUITE_SIZE) != 0u) {
89 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15342,
90 logStr, ALERT_DECODE_ERROR);
91 }
92 if (cipherSuitesLen == 0u) {
93 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15701,
94 logStr, ALERT_ILLEGAL_PARAMETER);
95 }
96
97 msg->cipherSuitesSize = cipherSuitesLen / SINGLE_CIPHER_SUITE_SIZE;
98 BSL_SAL_FREE(msg->cipherSuites);
99 msg->cipherSuites = (uint16_t *)BSL_SAL_Malloc(((uint32_t)msg->cipherSuitesSize) * sizeof(uint16_t));
100 if (msg->cipherSuites == NULL) {
101 return ParseErrorProcess(pkt->ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID15702,
102 BINGLOG_STR("cipherSuites malloc fail"), ALERT_UNKNOWN);
103 }
104 /* Parse the cipher suite */
105 for (uint16_t index = 0u; index < msg->cipherSuitesSize; index++) {
106 msg->cipherSuites[index] = BSL_ByteToUint16(&pkt->buf[*pkt->bufOffset]);
107 *pkt->bufOffset += sizeof(uint16_t);
108 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15703, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
109 "got cipher suite from client:0x%x.", msg->cipherSuites[index], 0, 0, 0);
110 if (msg->cipherSuites[index] == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) {
111 msg->haveEmptyRenegoScsvCipher = true;
112 }
113 if (msg->cipherSuites[index] == TLS_FALLBACK_SCSV) {
114 msg->haveFallBackScsvCipher = true;
115 }
116 }
117 #ifdef HITLS_TLS_CONNECTION_INFO_NEGOTIATION
118 ret = StoreClientCipherSuites(pkt->ctx, msg);
119 #endif
120 return ret;
121 }
122
123 /**
124 * @brief List of compression methods for parsing Client Hello messages
125 *
126 * @param pkt [IN] parse context
127 * @param msg [OUT] Client Hello Structure
128 *
129 * @retval HITLS_SUCCESS parsed successfully.
130 * @retval HITLS_PARSE_INVALID_MSG_LEN The message length is incorrect.
131 * @retval HITLS_MEMALLOC_FAIL Memory application failed.
132 */
ParseClientHelloCompressionMethods(ParsePacket * pkt,ClientHelloMsg * msg)133 static int32_t ParseClientHelloCompressionMethods(ParsePacket *pkt, ClientHelloMsg *msg)
134 {
135 uint8_t compressionMethodsLen = 0;
136 const char *logStr = BINGLOG_STR("parse compressionMethod failed.");
137 int32_t ret = ParseBytesToUint8(pkt, &compressionMethodsLen);
138 if (ret != HITLS_SUCCESS) {
139 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15704,
140 logStr, ALERT_DECODE_ERROR);
141 }
142
143 if ((compressionMethodsLen > (pkt->bufLen - *pkt->bufOffset)) || (compressionMethodsLen == 0u)) {
144 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15705,
145 logStr, ALERT_DECODE_ERROR);
146 }
147
148 ret = ParseBytesToArray(pkt, &msg->compressionMethods, compressionMethodsLen);
149 if (ret == HITLS_MEMALLOC_FAIL) {
150 return ParseErrorProcess(pkt->ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID16146,
151 BINGLOG_STR("compressionMethods malloc fail."), ALERT_UNKNOWN);
152 }
153
154 msg->compressionMethodsSize = compressionMethodsLen;
155
156 for (uint32_t i = 0; i < compressionMethodsLen; i++) {
157 if (msg->compressionMethods[i] == 0u) {
158 return HITLS_SUCCESS;
159 }
160 }
161
162 return ParseErrorProcess(pkt->ctx, HITLS_MSG_HANDLE_INVALID_COMPRESSION_METHOD, BINLOG_ID16238,
163 logStr, ALERT_DECODE_ERROR);
164 }
165
166 /**
167 * @brief Parse the Client Hello extension messages.
168 *
169 * @param pkt [IN] parse context
170 * @param msg [OUT] Client Hello Structure
171 *
172 * @retval HITLS_SUCCESS parsed successfully.
173 * @retval HITLS_PARSE_INVALID_MSG_LEN The message length is incorrect.
174 * @retval HITLS_PARSE_DUPLICATE_EXTENSIVE_MSG Extended message
175 */
ParseClientHelloExtensions(ParsePacket * pkt,ClientHelloMsg * msg)176 static int32_t ParseClientHelloExtensions(ParsePacket *pkt, ClientHelloMsg *msg)
177 {
178 uint16_t exMsgLen = 0;
179 const char *logStr = BINGLOG_STR("parse extension length failed.");
180 int32_t ret = ParseBytesToUint16(pkt, &exMsgLen);
181 if (ret != HITLS_SUCCESS) {
182 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15707,
183 logStr, ALERT_DECODE_ERROR);
184 }
185
186 if (exMsgLen != (pkt->bufLen - *pkt->bufOffset)) {
187 return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15708,
188 logStr, ALERT_DECODE_ERROR);
189 }
190
191 if (exMsgLen == 0u) {
192 return HITLS_SUCCESS;
193 }
194
195 return ParseClientExtension(pkt->ctx, &pkt->buf[*pkt->bufOffset], exMsgLen, msg);
196 }
197
ParseClientHello(TLS_Ctx * ctx,const uint8_t * data,uint32_t len,HS_Msg * hsMsg)198 int32_t ParseClientHello(TLS_Ctx *ctx, const uint8_t *data, uint32_t len, HS_Msg *hsMsg)
199 {
200 ClientHelloMsg *msg = &hsMsg->body.clientHello;
201 uint32_t bufOffset = 0;
202 ParsePacket pkt = {.ctx = ctx, .buf = data, .bufLen = len, .bufOffset = &bufOffset};
203 /* Parse the version number. The version number occupies two bytes */
204 int32_t ret = ParseVersion(&pkt, &msg->version);
205 if (ret != HITLS_SUCCESS) {
206 return ret;
207 }
208
209 ctx->negotiatedInfo.clientVersion = msg->version;
210 /* Parse the random number. The random number occupies 32 bytes */
211 ret = ParseRandom(&pkt, msg->randomValue, HS_RANDOM_SIZE);
212 if (ret != HITLS_SUCCESS) {
213 return ret;
214 }
215
216 ret = ParseSessionId(&pkt, &msg->sessionIdSize, &msg->sessionId);
217 if (ret != HITLS_SUCCESS) {
218 return ret;
219 }
220
221 #ifdef HITLS_TLS_PROTO_DTLS12
222 if (IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask)) {
223 /* Cookies need to be parsed in DTLS */
224 ret = ParseCookie(&pkt, &msg->cookieLen, &msg->cookie);
225 if (ret != HITLS_SUCCESS) {
226 return ret;
227 }
228 }
229 #endif
230 /* Parse the cipher suite. After the parsing is complete, update the msg->cipherSuitesSize and msg->cipherSuites */
231 ret = ParseClientHelloCipherSuites(&pkt, msg);
232 if (ret != HITLS_SUCCESS) {
233 return ret;
234 }
235 /* Parse compression method */
236 ret = ParseClientHelloCompressionMethods(&pkt, msg);
237 if (ret != HITLS_SUCCESS) {
238 return ret;
239 }
240
241 if (len == bufOffset) {
242 return HITLS_SUCCESS;
243 }
244 return ParseClientHelloExtensions(&pkt, msg);
245 }
246
CleanClientHello(ClientHelloMsg * msg)247 void CleanClientHello(ClientHelloMsg *msg)
248 {
249 // The value of msg->refCnt is not 0, indicating that the ClientHelloMsg resource is hosted in the hrr scenario
250 if (msg == NULL || msg->refCnt != 0) {
251 return;
252 }
253
254 BSL_SAL_FREE(msg->sessionId);
255 BSL_SAL_FREE(msg->cookie);
256 BSL_SAL_FREE(msg->cipherSuites);
257 BSL_SAL_FREE(msg->compressionMethods);
258
259 CleanClientHelloExtension(msg);
260
261 return;
262 }
263 #endif /* HITLS_TLS_HOST_SERVER */