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 #include "securec.h"
17 #include "bsl_sal.h"
18 #include "tls_binlog_id.h"
19 #include "bsl_log_internal.h"
20 #include "bsl_log.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_bytes.h"
23 #include "hitls_error.h"
24 #include "hitls_config.h"
25 #include "bsl_errno.h"
26 #include "bsl_uio.h"
27 #include "tls.h"
28 #include "uio_base.h"
29 #include "record.h"
30 #include "hs_ctx.h"
31 #ifdef HITLS_TLS_FEATURE_INDICATOR
32 #include "indicator.h"
33 #endif
34 #include "hs.h"
35 #include "rec_crypto.h"
36
37
GetWriteConnState(const TLS_Ctx * ctx)38 RecConnState *GetWriteConnState(const TLS_Ctx *ctx)
39 {
40 /** Obtain the record structure. */
41 RecCtx *recordCtx = (RecCtx *)ctx->recCtx;
42 return recordCtx->writeStates.currentState;
43 }
44
OutbufUpdate(uint32_t * start,uint32_t startvalue,uint32_t * end,uint32_t endvalue)45 static void OutbufUpdate(uint32_t *start, uint32_t startvalue, uint32_t *end, uint32_t endvalue)
46 {
47 /** Commit the record to be written */
48 *start = startvalue;
49 *end = endvalue;
50 return;
51 }
52
CheckEncryptionLimits(TLS_Ctx * ctx,RecConnState * state)53 static int32_t CheckEncryptionLimits(TLS_Ctx *ctx, RecConnState *state)
54 {
55 (void)ctx;
56 if (state->suiteInfo != NULL &&
57 #ifdef HITLS_TLS_FEATURE_KEY_UPDATE
58 ctx->isKeyUpdateRequest == false &&
59 #endif
60 (state->suiteInfo->cipherAlg == HITLS_CIPHER_AES_128_GCM ||
61 state->suiteInfo->cipherAlg == HITLS_CIPHER_AES_256_GCM) &&
62 RecConnGetSeqNum(state) > REC_MAX_AES_GCM_ENCRYPTION_LIMIT) {
63 BSL_ERR_PUSH_ERROR(HITLS_REC_ENCRYPTED_NUMBER_OVERFLOW);
64 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16188, BSL_LOG_LEVEL_WARN, BSL_LOG_BINLOG_TYPE_RUN,
65 "AES-GCM record encrypted times overflow", 0, 0, 0, 0);
66 return HITLS_REC_ENCRYPTED_NUMBER_OVERFLOW;
67 }
68 return HITLS_SUCCESS;
69 }
70
71 #ifdef HITLS_TLS_PROTO_DTLS12
72 // Write the data message.
DatagramWrite(TLS_Ctx * ctx,RecBuf * buf)73 static int32_t DatagramWrite(TLS_Ctx *ctx, RecBuf *buf)
74 {
75 uint32_t total = buf->end - buf->start;
76
77 /* Attempt to write */
78 uint32_t sendLen = 0u;
79 #ifdef HITLS_TLS_CONFIG_STATE
80 ctx->rwstate = HITLS_WRITING;
81 #endif
82 int32_t ret = BSL_UIO_Write(ctx->uio, &(buf->buf[buf->start]), total, &sendLen);
83 /* Two types of failures occur in the packet transfer scenario:
84 * a. The bottom layer directly returns a failure message.
85 * b. Only some data packets are sent.
86 * (sendLen != total) && (sendLen != 0) checks whether the returned result is null, but only part of the data is
87 sent */
88 if ((ret != BSL_SUCCESS) || ((sendLen != 0) && (sendLen != total))) {
89 BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_IO_EXCEPTION);
90 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15664, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
91 "Record send: IO exception. %d\n", ret, 0, 0, 0);
92 return HITLS_REC_ERR_IO_EXCEPTION;
93 }
94
95 if (sendLen == 0) {
96 return HITLS_REC_NORMAL_IO_BUSY;
97 }
98
99 buf->start = 0;
100 buf->end = 0;
101 #ifdef HITLS_TLS_CONFIG_STATE
102 ctx->rwstate = HITLS_NOTHING;
103 #endif
104 return HITLS_SUCCESS;
105 }
106
DtlsPlainMsgGenerate(REC_TextInput * plainMsg,const TLS_Ctx * ctx,REC_Type recordType,const uint8_t * data,uint32_t plainLen,uint64_t epochSeq)107 void DtlsPlainMsgGenerate(REC_TextInput *plainMsg, const TLS_Ctx *ctx,
108 REC_Type recordType, const uint8_t *data, uint32_t plainLen, uint64_t epochSeq)
109 {
110 plainMsg->type = recordType;
111 plainMsg->text = data;
112 plainMsg->textLen = plainLen;
113 plainMsg->negotiatedVersion = ctx->negotiatedInfo.version;
114 #ifdef HITLS_TLS_FEATURE_ETM
115 plainMsg->isEncryptThenMac = ctx->negotiatedInfo.isEncryptThenMac;
116 #endif
117
118 if (ctx->negotiatedInfo.version == 0) {
119 plainMsg->version = HITLS_VERSION_DTLS10;
120 if (IS_SUPPORT_TLCP(ctx->config.tlsConfig.originVersionMask)) {
121 plainMsg->version = HITLS_VERSION_TLCP_DTLCP11;
122 }
123 } else {
124 plainMsg->version = ctx->negotiatedInfo.version;
125 }
126
127 BSL_Uint64ToByte(epochSeq, plainMsg->seq);
128 }
129
DtlsRecordHeaderPack(uint8_t * outBuf,REC_Type recordType,uint16_t version,uint64_t epochSeq,uint32_t cipherTextLen)130 static inline void DtlsRecordHeaderPack(uint8_t *outBuf, REC_Type recordType, uint16_t version,
131 uint64_t epochSeq, uint32_t cipherTextLen)
132 {
133 outBuf[0] = recordType;
134 BSL_Uint16ToByte(version, &outBuf[1]);
135
136 BSL_Uint64ToByte(epochSeq, &outBuf[REC_DTLS_RECORD_EPOCH_OFFSET]);
137 BSL_Uint16ToByte((uint16_t)cipherTextLen, &outBuf[REC_DTLS_RECORD_LENGTH_OFFSET]);
138 }
139
DtlsRecOutBufInit(RecCtx * recordCtx,uint32_t bufSize)140 static int32_t DtlsRecOutBufInit(RecCtx *recordCtx, uint32_t bufSize)
141 {
142 if (recordCtx->outBuf == NULL) {
143 recordCtx->outBuf = RecBufNew(bufSize);
144 if (recordCtx->outBuf == NULL) {
145 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17279, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
146 "RecBufNew fail", 0, 0, 0, 0);
147 return HITLS_MEMALLOC_FAIL;
148 }
149 }
150 return HITLS_SUCCESS;
151 }
152
DtlsTrySendMessage(TLS_Ctx * ctx,RecCtx * recordCtx,REC_Type recordType,RecConnState * state)153 static int32_t DtlsTrySendMessage(TLS_Ctx *ctx, RecCtx *recordCtx, REC_Type recordType, RecConnState *state)
154 {
155 /* Notify the uio whether the service message is being sent. rfc6083 4.4. Stream Usage: For non-app messages, the
156 * sctp stream id number must be 0 */
157 bool isAppMsg = (recordType == REC_TYPE_APP);
158 (void)BSL_UIO_Ctrl(ctx->uio, BSL_UIO_SCTP_MASK_APP_MESSAGE, sizeof(isAppMsg), &isAppMsg);
159
160 int32_t ret = DatagramWrite(ctx, recordCtx->outBuf);
161 if (ret != HITLS_SUCCESS) {
162 /* Does not cache messages in the DTLS */
163 recordCtx->outBuf->start = 0;
164 recordCtx->outBuf->end = 0;
165 return ret;
166 }
167
168 #if defined(HITLS_BSL_UIO_UDP)
169 ret = RecDerefBufList(ctx);
170 if (ret != HITLS_SUCCESS) {
171 return ret;
172 }
173 #endif
174 /** Add the record sequence */
175 RecConnSetSeqNum(state, state->seq + 1);
176
177 return HITLS_SUCCESS;
178 }
179
180 // Write a record for the DTLS protocol
DtlsRecordWrite(TLS_Ctx * ctx,REC_Type recordType,const uint8_t * data,uint32_t num)181 int32_t DtlsRecordWrite(TLS_Ctx *ctx, REC_Type recordType, const uint8_t *data, uint32_t num)
182 {
183 /** Obtain the record structure */
184 RecCtx *recordCtx = (RecCtx *)ctx->recCtx;
185 RecConnState *state = GetWriteConnState(ctx);
186
187 if (state->seq > REC_DTLS_SN_MAX_VALUE) {
188 BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_SN_WRAPPING);
189 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15665, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
190 "Record write: sequence number wrap.", 0, 0, 0, 0);
191 return HITLS_REC_ERR_SN_WRAPPING;
192 }
193
194 uint32_t cipherTextLen = RecGetCryptoFuncs(state->suiteInfo)->calCiphertextLen(ctx, state->suiteInfo, num, false);
195 if (cipherTextLen == 0) {
196 BSL_ERR_PUSH_ERROR(HITLS_INTERNAL_EXCEPTION);
197 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15666, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
198 "Record write: cipherTextLen(0) error.", 0, 0, 0, 0);
199 return HITLS_INTERNAL_EXCEPTION;
200 }
201 int32_t ret = DtlsRecOutBufInit(recordCtx, RecGetInitBufferSize(ctx, false));
202 if (ret != HITLS_SUCCESS) {
203 return ret;
204 }
205
206 const uint32_t outBufLen = REC_DTLS_RECORD_HEADER_LEN + cipherTextLen;
207 if (outBufLen > recordCtx->outBuf->bufSize) {
208 BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_BUFFER_NOT_ENOUGH);
209 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15667, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
210 "DTLS record write error: msg len = %u, buf len = %u.", outBufLen, recordCtx->outBuf->bufSize, 0, 0);
211 return HITLS_REC_ERR_BUFFER_NOT_ENOUGH;
212 }
213
214 /* Before encryption, construct plaintext parameters */
215 REC_TextInput plainMsg = {0};
216 uint64_t epochSeq = REC_EPOCHSEQ_CAL(RecConnGetEpoch(state), state->seq);
217 DtlsPlainMsgGenerate(&plainMsg, ctx, recordType, data, num, epochSeq);
218
219 /** Obtain the cache address */
220 uint8_t *outBuf = &recordCtx->outBuf->buf[0];
221
222 DtlsRecordHeaderPack(outBuf, recordType, plainMsg.version, epochSeq, cipherTextLen);
223
224 ret = CheckEncryptionLimits(ctx, state);
225 if (ret != HITLS_SUCCESS) {
226 return ret;
227 }
228
229 /** Encrypt the record body */
230 ret = RecConnEncrypt(ctx, state, &plainMsg, &outBuf[REC_DTLS_RECORD_HEADER_LEN], cipherTextLen);
231 if (ret != HITLS_SUCCESS) {
232 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17280, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
233 "RecConnEncrypt fail", 0, 0, 0, 0);
234 return ret;
235 }
236
237 OutbufUpdate(&recordCtx->outBuf->start, 0, &recordCtx->outBuf->end, outBufLen);
238
239 #ifdef HITLS_TLS_FEATURE_INDICATOR
240 INDICATOR_MessageIndicate(1, 0, RECORD_HEADER, outBuf, REC_DTLS_RECORD_HEADER_LEN,
241 ctx, ctx->config.tlsConfig.msgArg);
242 #endif
243
244 return DtlsTrySendMessage(ctx, recordCtx, recordType, state);
245 }
246 #endif /* HITLS_TLS_PROTO_DTLS12 */
247
248 #ifdef HITLS_TLS_PROTO_TLS
249 // Writes data to the UIO of the TLS context.
StreamWrite(TLS_Ctx * ctx,RecBuf * buf)250 int32_t StreamWrite(TLS_Ctx *ctx, RecBuf *buf)
251 {
252 uint32_t total = buf->end - buf->start;
253 int32_t ret = BSL_SUCCESS;
254 #ifdef HITLS_TLS_CONFIG_STATE
255 ctx->rwstate = HITLS_WRITING;
256 #endif
257 do {
258 uint32_t sendLen = 0u;
259 ret = BSL_UIO_Write(ctx->uio, &(buf->buf[buf->start]), total, &sendLen);
260 if (ret != BSL_SUCCESS) {
261 BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_IO_EXCEPTION);
262 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15668, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
263 "Record send: IO exception. %d\n", ret, 0, 0, 0);
264 return HITLS_REC_ERR_IO_EXCEPTION;
265 }
266
267 if (sendLen == 0) {
268 return HITLS_REC_NORMAL_IO_BUSY;
269 }
270
271 buf->start += sendLen;
272 total -= sendLen;
273 } while (buf->start < buf->end);
274
275 buf->start = 0;
276 buf->end = 0;
277 #ifdef HITLS_TLS_CONFIG_STATE
278 ctx->rwstate = HITLS_NOTHING;
279 #endif
280
281 return HITLS_SUCCESS;
282 }
283
TlsPlainMsgGenerate(REC_TextInput * plainMsg,const TLS_Ctx * ctx,REC_Type recordType,const uint8_t * data,uint32_t plainLen)284 static void TlsPlainMsgGenerate(REC_TextInput *plainMsg, const TLS_Ctx *ctx,
285 REC_Type recordType, const uint8_t *data, uint32_t plainLen)
286 {
287 plainMsg->type = recordType;
288 plainMsg->text = data;
289 plainMsg->textLen = plainLen;
290 plainMsg->negotiatedVersion = ctx->negotiatedInfo.version;
291 #ifdef HITLS_TLS_FEATURE_ETM
292 plainMsg->isEncryptThenMac = ctx->negotiatedInfo.isEncryptThenMacWrite;
293 #endif
294 if (ctx->negotiatedInfo.version != 0) {
295 plainMsg->version =
296 #ifdef HITLS_TLS_PROTO_TLS13
297 (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) ? HITLS_VERSION_TLS12 :
298 #endif
299 ctx->negotiatedInfo.version;
300 } else {
301 plainMsg->version =
302 #ifdef HITLS_TLS_PROTO_TLS13
303 (ctx->config.tlsConfig.maxVersion == HITLS_VERSION_TLS13) ? HITLS_VERSION_TLS12 :
304 #endif
305 ctx->config.tlsConfig.maxVersion;
306 }
307
308 if (ctx->hsCtx != NULL && ctx->hsCtx->state == TRY_SEND_CLIENT_HELLO &&
309 ctx->state != CM_STATE_RENEGOTIATION &&
310 #ifdef HITLS_TLS_PROTO_TLS13
311 ctx->hsCtx->haveHrr == false &&
312 #endif
313 #ifdef HITLS_TLS_PROTO_TLCP11
314 ctx->config.tlsConfig.maxVersion != HITLS_VERSION_TLCP_DTLCP11 &&
315 #endif
316 ctx->config.tlsConfig.maxVersion > HITLS_VERSION_TLS10) {
317 plainMsg->version = HITLS_VERSION_TLS10;
318 }
319
320 BSL_Uint64ToByte(GetWriteConnState(ctx)->seq, plainMsg->seq);
321 }
322
TlsRecordHeaderPack(uint8_t * outBuf,REC_Type recordType,uint16_t version,uint32_t cipherTextLen)323 static inline void TlsRecordHeaderPack(uint8_t *outBuf, REC_Type recordType, uint16_t version, uint32_t cipherTextLen)
324 {
325 outBuf[0] = recordType;
326 BSL_Uint16ToByte(version, &outBuf[1]);
327 BSL_Uint16ToByte((uint16_t)cipherTextLen, &outBuf[REC_TLS_RECORD_LENGTH_OFFSET]);
328 }
329
SendRecord(TLS_Ctx * ctx,RecCtx * recordCtx,RecConnState * state,uint64_t seq)330 static int32_t SendRecord(TLS_Ctx *ctx, RecCtx *recordCtx, RecConnState *state, uint64_t seq)
331 {
332 int32_t ret = StreamWrite(ctx, recordCtx->outBuf);
333 if (ret != HITLS_SUCCESS) {
334 return ret;
335 }
336
337 /** Add the record sequence */
338 RecConnSetSeqNum(state, seq + 1);
339 return HITLS_SUCCESS;
340 }
SequenceCompare(RecConnState * state,uint64_t value)341 static int32_t SequenceCompare(RecConnState *state, uint64_t value)
342 {
343 if (state->isWrapped == true) {
344 BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_SN_WRAPPING);
345 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15670, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
346 "Record write: sequence number wrap.", 0, 0, 0, 0);
347 return HITLS_REC_ERR_SN_WRAPPING;
348 }
349 if (state->seq == value) {
350 state->isWrapped = true;
351 }
352 return HITLS_SUCCESS;
353 }
354
LengthCheck(uint32_t ciphertextLen,const uint32_t outBufLen,RecBuf * writeBuf)355 static int32_t LengthCheck(uint32_t ciphertextLen, const uint32_t outBufLen, RecBuf *writeBuf)
356 {
357 if (ciphertextLen == 0) {
358 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15671, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
359 "Record write: cipherTextLen(0) error.", 0, 0, 0, 0);
360 return HITLS_INTERNAL_EXCEPTION;
361 }
362 if (outBufLen > writeBuf->bufSize) {
363 BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_BUFFER_NOT_ENOUGH);
364 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15672, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
365 "Record write: buffer is not enough.", 0, 0, 0, 0);
366 return HITLS_REC_ERR_BUFFER_NOT_ENOUGH;
367 }
368 return HITLS_SUCCESS;
369 }
GetPlainMsgData(RecordPlaintext * recPlaintext,const uint8_t * data)370 static const uint8_t *GetPlainMsgData(RecordPlaintext *recPlaintext, const uint8_t *data)
371 {
372 (void)recPlaintext;
373 return
374 #ifdef HITLS_TLS_PROTO_TLS13
375 recPlaintext->isTlsInnerPlaintext ? recPlaintext->plainData :
376 #endif
377 data;
378 }
379 // Write a record in the TLS protocol, serialize a record message, and send the message
TlsRecordWrite(TLS_Ctx * ctx,REC_Type recordType,const uint8_t * data,uint32_t num)380 int32_t TlsRecordWrite(TLS_Ctx *ctx, REC_Type recordType, const uint8_t *data, uint32_t num)
381 {
382 RecBuf *writeBuf = ctx->recCtx->outBuf;
383 RecConnState *state = GetWriteConnState(ctx);
384 RecordPlaintext recPlaintext = {0};
385 REC_TextInput plainMsg = {0};
386 int32_t ret = SequenceCompare(state, REC_TLS_SN_MAX_VALUE);
387 if (ret != HITLS_SUCCESS) {
388 return ret;
389 }
390 /* Check whether the cache exists */
391 if (writeBuf->end > writeBuf->start) {
392 return SendRecord(ctx, ctx->recCtx, state, state->seq);
393 }
394 const RecCryptoFunc *funcs = RecGetCryptoFuncs(state->suiteInfo);
395 ret = funcs->encryptPreProcess(ctx, recordType, data, num, &recPlaintext);
396 if (ret != HITLS_SUCCESS) {
397 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17281, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
398 "encryptPreProcess fail", 0, 0, 0, 0);
399 return ret;
400 }
401
402 uint32_t ciphertextLen = funcs->calCiphertextLen(ctx, state->suiteInfo, recPlaintext.plainLen, false);
403 const uint32_t outBufLen = REC_TLS_RECORD_HEADER_LEN + ciphertextLen;
404 ret = LengthCheck(ciphertextLen, outBufLen, writeBuf);
405 if (ret != HITLS_SUCCESS) {
406 BSL_SAL_FREE(recPlaintext.plainData);
407 return ret;
408 }
409 /* If the value is not tls13, use the input parameter data */
410 const uint8_t *plainMsgData = GetPlainMsgData(&recPlaintext, data);
411 (void)TlsPlainMsgGenerate(&plainMsg, ctx, recPlaintext.recordType, plainMsgData, recPlaintext.plainLen);
412 (void)TlsRecordHeaderPack(writeBuf->buf, recPlaintext.recordType, plainMsg.version, ciphertextLen);
413
414 ret = CheckEncryptionLimits(ctx, state);
415 if (ret != HITLS_SUCCESS) {
416 BSL_SAL_FREE(recPlaintext.plainData);
417 return ret;
418 }
419
420 /** Encrypt the record body */
421 ret = RecConnEncrypt(ctx, state, &plainMsg, writeBuf->buf + REC_TLS_RECORD_HEADER_LEN, ciphertextLen);
422 BSL_SAL_FREE(recPlaintext.plainData);
423 if (ret != HITLS_SUCCESS) {
424 return ret;
425 }
426
427 #ifdef HITLS_TLS_FEATURE_INDICATOR
428 INDICATOR_MessageIndicate(1, recordType, RECORD_HEADER, writeBuf->buf, REC_TLS_RECORD_HEADER_LEN, ctx,
429 ctx->config.tlsConfig.msgArg);
430 #endif
431 OutbufUpdate(&writeBuf->start, 0, &writeBuf->end, outBufLen);
432
433 return SendRecord(ctx, ctx->recCtx, state, state->seq);
434 }
435 #endif /* HITLS_TLS_PROTO_TLS */
436