• 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 #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