• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */