* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "hitls_build.h"
#include "bsl_sal.h"
#include "tls_binlog_id.h"
#include "hitls_error.h"
#include "hitls_sni.h"
#include "bsl_err_internal.h"
#ifdef HITLS_TLS_FEATURE_INDICATOR
#include "indicator.h"
#endif
#include "hs_reass.h"
#include "hs_common.h"
#include "hs_verify.h"
#include "hs_kx.h"
#include "hs.h"
#include "parse.h"
#ifdef HITLS_TLS_FEATURE_FLIGHT
static int32_t UIO_Init(TLS_Ctx *ctx)
{
if (ctx->bUio != NULL) {
return HITLS_SUCCESS;
}
int32_t ret = HITLS_SUCCESS;
BSL_UIO *bUio = BSL_UIO_New(BSL_UIO_BufferMethod());
if (bUio == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17172, BSL_LOG_LEVEL_FATAL, BSL_LOG_BINLOG_TYPE_RUN, "UIO_New fail", 0, 0, 0, 0);
return HITLS_MEMALLOC_FAIL;
}
#if defined(HITLS_TLS_PROTO_DTLS12) && defined(HITLS_BSL_UIO_UDP)
uint32_t bufferLen = (uint32_t)ctx->config.pmtu;
if (IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask) &&
BSL_UIO_GetUioChainTransportType(ctx->uio, BSL_UIO_UDP)) {
ret = BSL_UIO_Ctrl(bUio, BSL_UIO_SET_BUFFER_SIZE, sizeof(uint32_t), &bufferLen);
if (ret != BSL_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17173, BSL_LOG_LEVEL_FATAL, BSL_LOG_BINLOG_TYPE_RUN,
"SET_BUFFER_SIZE fail, ret %d", ret, 0, 0, 0);
BSL_UIO_Free(bUio);
BSL_ERR_PUSH_ERROR(HITLS_UIO_FAIL);
return HITLS_UIO_FAIL;
}
}
#endif
ctx->bUio = bUio;
ret = BSL_UIO_Append(bUio, ctx->uio);
if (ret != BSL_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17174, BSL_LOG_LEVEL_FATAL, BSL_LOG_BINLOG_TYPE_RUN,
"UIO_Append fail, ret %d", ret, 0, 0, 0);
BSL_UIO_Free(bUio);
ctx->bUio = NULL;
return ret;
}
ctx->uio = bUio;
return HITLS_SUCCESS;
}
static int32_t UIO_Deinit(TLS_Ctx *ctx)
{
if (ctx->bUio == NULL) {
return HITLS_SUCCESS;
}
ctx->uio = BSL_UIO_PopCurrent(ctx->uio);
BSL_UIO_FreeChain(ctx->bUio);
ctx->bUio = NULL;
return HITLS_SUCCESS;
}
#endif
static int32_t HsInitChangeState(TLS_Ctx *ctx)
{
if (ctx->isClient) {
return HS_ChangeState(ctx, TRY_SEND_CLIENT_HELLO);
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
if (ctx->negotiatedInfo.isRenegotiation) {
return HS_ChangeState(ctx, TRY_SEND_HELLO_REQUEST);
}
#endif
return HS_ChangeState(ctx, TRY_RECV_CLIENT_HELLO);
}
int32_t NewHsCtxConfig(TLS_Ctx *ctx, HS_Ctx *hsCtx)
{
(void)ctx;
if (VERIFY_Init(hsCtx) != HITLS_SUCCESS) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID17178, "VERIFY_Init fail");
}
#ifdef HITLS_TLS_FEATURE_FLIGHT
if (ctx->config.tlsConfig.isFlightTransmitEnable == true && UIO_Init(ctx) != HITLS_SUCCESS) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID17179, "UIO_Init fail");
}
#endif
hsCtx->kxCtx = HS_KeyExchCtxNew();
if (hsCtx->kxCtx == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID17180, "KeyExchCtxNew fail");
}
#ifdef HITLS_TLS_PROTO_TLS13
hsCtx->firstClientHello = NULL;
#endif
#ifdef HITLS_TLS_PROTO_DTLS12
hsCtx->reassMsg = HS_ReassNew();
if (hsCtx->reassMsg == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID17181, "ReassNew fail");
}
#endif
#ifdef HITLS_TLS_FEATURE_INDICATOR
INDICATOR_StatusIndicate(ctx, INDICATE_EVENT_HANDSHAKE_START, INDICATE_VALUE_SUCCESS);
#endif
return HITLS_SUCCESS;
}
int32_t HS_Init(TLS_Ctx *ctx)
{
int32_t ret = HITLS_SUCCESS;
if (ctx == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_NULL_INPUT, BINLOG_ID17175, "ctx null");
}
if (ctx->hsCtx != NULL) {
return HITLS_SUCCESS;
}
HS_Ctx *hsCtx = (HS_Ctx *)BSL_SAL_Calloc(1u, sizeof(HS_Ctx));
if (hsCtx == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID17176, "Calloc fail");
}
ctx->hsCtx = hsCtx;
hsCtx->clientRandom = ctx->negotiatedInfo.clientRandom;
hsCtx->serverRandom = ctx->negotiatedInfo.serverRandom;
hsCtx->bufferLen = HITLS_HS_INIT_BUFFER_SIZE;
hsCtx->msgBuf = BSL_SAL_Malloc(hsCtx->bufferLen);
if (hsCtx->msgBuf == NULL) {
(void)RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID17177, "Malloc fail");
goto exit;
}
ret = NewHsCtxConfig(ctx, hsCtx);
if (ret != HITLS_SUCCESS) {
goto exit;
}
return HsInitChangeState(ctx);
exit:
HS_DeInit(ctx);
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
return HITLS_MEMALLOC_FAIL;
}
void HS_DeInit(TLS_Ctx *ctx)
{
if (ctx == NULL || ctx->hsCtx == NULL) {
return;
}
HS_Ctx *hsCtx = ctx->hsCtx;
HS_CleanMsg(ctx->hsCtx->hsMsg);
BSL_SAL_FREE(ctx->hsCtx->hsMsg);
BSL_SAL_FREE(hsCtx->msgBuf);
#if defined(HITLS_TLS_FEATURE_SESSION) || defined(HITLS_TLS_PROTO_TLS13)
BSL_SAL_FREE(hsCtx->sessionId);
#endif
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
BSL_SAL_FREE(hsCtx->ticket);
#endif
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->hsCtx->firstClientHello != NULL) {
HS_Msg hsMsg = {0};
hsMsg.type = CLIENT_HELLO;
hsMsg.body.clientHello = *ctx->hsCtx->firstClientHello;
HS_CleanMsg(&hsMsg);
BSL_SAL_FREE(ctx->hsCtx->firstClientHello);
}
#endif
BSL_SAL_CleanseData(hsCtx->masterKey, MAX_DIGEST_SIZE);
#ifdef HITLS_TLS_PROTO_TLS13
BSL_SAL_CleanseData(ctx->hsCtx->earlySecret, MAX_DIGEST_SIZE);
BSL_SAL_CleanseData(ctx->hsCtx->handshakeSecret, MAX_DIGEST_SIZE);
BSL_SAL_CleanseData(ctx->hsCtx->serverHsTrafficSecret, MAX_DIGEST_SIZE);
BSL_SAL_CleanseData(ctx->hsCtx->clientHsTrafficSecret, MAX_DIGEST_SIZE);
#endif
if (hsCtx->peerCert != NULL) {
SAL_CERT_PairFree(ctx->config.tlsConfig.certMgrCtx, hsCtx->peerCert);
hsCtx->peerCert = NULL;
}
VERIFY_Deinit(hsCtx);
#ifdef HITLS_TLS_FEATURE_FLIGHT
if (ctx->config.tlsConfig.isFlightTransmitEnable == true) {
UIO_Deinit(ctx);
}
#endif
HS_KeyExchCtxFree(hsCtx->kxCtx);
#ifdef HITLS_TLS_PROTO_DTLS12
HS_ReassFree(hsCtx->reassMsg);
#endif
BSL_SAL_FREE(ctx->hsCtx);
return;
}