* 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"
#if defined(HITLS_TLS_FEATURE_SESSION_TICKET) && defined(HITLS_TLS_HOST_SERVER)
#include <string.h>
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_err_internal.h"
#include "bsl_bytes.h"
#include "bsl_sal.h"
#include "hitls_error.h"
#include "rec.h"
#include "hs_ctx.h"
#include "hs_kx.h"
#include "hs_common.h"
#include "session_mgr.h"
#include "pack.h"
#include "send_process.h"
#ifdef HITLS_TLS_PROTO_TLS13
#define HITLS_ONE_WEEK_SECONDS (604800)
#endif
#ifdef HITLS_TLS_PROTO_TLS_BASIC
int32_t SendNewSessionTicketProcess(TLS_Ctx *ctx)
{
int32_t ret;
HS_Ctx *hsCtx = ctx->hsCtx;
TLS_SessionMgr *sessMgr = ctx->globalConfig->sessMgr;
if (hsCtx->msgLen == 0) {
hsCtx->ticketLifetimeHint = (uint32_t)SESSMGR_GetTimeout(sessMgr);
BSL_SAL_FREE(hsCtx->ticket);
hsCtx->ticketSize = 0;
ret = SESSMGR_EncryptSessionTicket(ctx, sessMgr, ctx->session, &hsCtx->ticket, &hsCtx->ticketSize);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16046, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SESSMGR_EncryptSessionTicket return fail when send new session ticket msg.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
ret = HS_PackMsg(ctx, NEW_SESSION_TICKET);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15978, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server pack new session ticket msg fail.", 0, 0, 0, 0);
return ret;
}
}
ret = HS_SendMsg(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15979, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"send new session ticket msg success.", 0, 0, 0, 0);
return HS_ChangeState(ctx, TRY_SEND_CHANGE_CIPHER_SPEC);
}
#endif
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t Tls13TicketGenerateConfigSession(TLS_Ctx *ctx, HITLS_Session **sessionPtr,
uint8_t *resumePsk, uint32_t hashLen)
{
int32_t ret = HITLS_SUCCESS;
HITLS_Session *newSession = NULL;
HS_Ctx *hsCtx = ctx->hsCtx;
newSession = SESS_Copy(ctx->session);
if (newSession == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16050, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"copy session info failed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MEMALLOC_FAIL;
}
SESS_SetStartTime(newSession, (uint64_t)BSL_SAL_CurrentSysTimeGet());
HITLS_SESS_SetTimeout(newSession, (uint64_t)hsCtx->ticketLifetimeHint);
HITLS_SESS_SetMasterKey(newSession, resumePsk, hashLen);
ret = SAL_CRYPT_Rand(LIBCTX_FROM_CTX(ctx), (uint8_t *)&hsCtx->ticketAgeAdd, sizeof(hsCtx->ticketAgeAdd));
if (ret != HITLS_SUCCESS) {
HITLS_SESS_Free(newSession);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16047, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"generate ticket_age_add value fail.", 0, 0, 0, 0);
return ret;
}
SESS_SetTicketAgeAdd(newSession, hsCtx->ticketAgeAdd);
*sessionPtr = newSession;
return HITLS_SUCCESS;
}
int32_t Tls13TicketGenerate(TLS_Ctx *ctx)
{
int32_t ret;
HITLS_Session *newSession = NULL;
HS_Ctx *hsCtx = ctx->hsCtx;
TLS_SessionMgr *sessMgr = ctx->globalConfig->sessMgr;
uint64_t timeout = SESSMGR_GetTimeout(sessMgr);
if (timeout > HITLS_ONE_WEEK_SECONDS) {
hsCtx->ticketLifetimeHint = HITLS_ONE_WEEK_SECONDS;
} else {
hsCtx->ticketLifetimeHint = (uint32_t)timeout;
}
BSL_SAL_FREE(hsCtx->ticket);
hsCtx->ticketSize = 0;
uint8_t resumePsk[MAX_DIGEST_SIZE] = {0};
uint32_t hashLen = SAL_CRYPT_DigestSize(ctx->negotiatedInfo.cipherSuiteInfo.hashAlg);
if (hashLen == 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17154, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "DigestSize err", 0, 0, 0, 0);
return HITLS_CRYPT_ERR_DIGEST;
}
uint8_t ticketNonce[sizeof(hsCtx->nextTicketNonce)] = {0};
BSL_Uint64ToByte(hsCtx->nextTicketNonce, ticketNonce);
ret = HS_TLS13DeriveResumePsk(ctx, ticketNonce, sizeof(ticketNonce), resumePsk, hashLen);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17155, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"DeriveResumePsk fail", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
BSL_SAL_CleanseData(resumePsk, MAX_DIGEST_SIZE);
return ret;
}
ret = Tls13TicketGenerateConfigSession(ctx, &newSession, resumePsk, hashLen);
if (ret != HITLS_SUCCESS) {
BSL_SAL_CleanseData(resumePsk, MAX_DIGEST_SIZE);
return ret;
}
ret = SESSMGR_EncryptSessionTicket(ctx, sessMgr, newSession, &hsCtx->ticket, &hsCtx->ticketSize);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16051, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"Encrypt Session Ticket failed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
HITLS_SESS_Free(newSession);
BSL_SAL_CleanseData(resumePsk, MAX_DIGEST_SIZE);
return ret;
}
HITLS_SESS_Free(ctx->session);
ctx->session = newSession;
BSL_SAL_CleanseData(resumePsk, MAX_DIGEST_SIZE);
return HITLS_SUCCESS;
}
int32_t Tls13SendNewSessionTicketProcess(TLS_Ctx *ctx)
{
int32_t ret;
HS_Ctx *hsCtx = ctx->hsCtx;
if (hsCtx->msgLen == 0) {
ret = Tls13TicketGenerate(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = HS_PackMsg(ctx, NEW_SESSION_TICKET);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16052, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server pack new session ticket msg fail.", 0, 0, 0, 0);
return ret;
}
}
ret = HS_SendMsg(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16053, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"send new session ticket msg success.", 0, 0, 0, 0);
hsCtx->sentTickets++;
hsCtx->nextTicketNonce++;
if (hsCtx->sentTickets >= ctx->config.tlsConfig.ticketNums || ctx->negotiatedInfo.isResume) {
return HS_ChangeState(ctx, TLS_CONNECTED);
}
return HS_ChangeState(ctx, TRY_SEND_NEW_SESSION_TICKET);
}
#endif
#endif