* 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_HOST_CLIENT) && defined(HITLS_TLS_FEATURE_SESSION_TICKET)
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_err_internal.h"
#include "bsl_sal.h"
#include "hitls_error.h"
#include "tls.h"
#include "hs_msg.h"
#include "hs_common.h"
#include "hs_extensions.h"
#include "parse_msg.h"
#include "parse_common.h"
#include "parse_extensions.h"
#include "custom_extensions.h"
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t ParseTicketNonce(ParsePacket *pkt, NewSessionTicketMsg *msg)
{
uint8_t ticketNonceSize = 0;
const char *logStr = BINGLOG_STR("ParseTicketNonce fail");
int32_t ret = ParseOneByteLengthField(pkt, &ticketNonceSize, &msg->ticketNonce);
if (ret == HITLS_PARSE_INVALID_MSG_LEN) {
return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID17010, logStr, ALERT_DECODE_ERROR);
} else if (ret == HITLS_MEMALLOC_FAIL) {
return ParseErrorProcess(pkt->ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID17011, logStr, ALERT_INTERNAL_ERROR);
}
msg->ticketNonceSize = (uint32_t)ticketNonceSize;
return HITLS_SUCCESS;
}
#endif
static int32_t ParseTicket(ParsePacket *pkt, NewSessionTicketMsg *msg)
{
bool isTls13 = (pkt->ctx->negotiatedInfo.version == HITLS_VERSION_TLS13);
uint16_t ticketSize = 0;
If the server does not include a ticket after including the SessionTicket extension in the ServerHello,
it sends a zero-length ticket in the NewSessionTicket handshake message */
int32_t ret = ParseTwoByteLengthField(pkt, &ticketSize, &msg->ticket);
if (ret == HITLS_PARSE_INVALID_MSG_LEN) {
return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16012,
BINGLOG_STR("parse ticketSize failed."), ALERT_DECODE_ERROR);
} else if (ret == HITLS_MEMALLOC_FAIL) {
return ParseErrorProcess(pkt->ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID15968,
BINGLOG_STR("malloc ticket failed."), ALERT_UNKNOWN);
}
if ((isTls13 && (ticketSize == 0)) ||
(!isTls13 && (pkt->bufLen != *pkt->bufOffset))) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15967, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"parse sesionticket message failed, bufLen %u, ticket size %u.", pkt->bufLen, ticketSize, 0, 0);
return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, 0, NULL, ALERT_DECODE_ERROR);
}
msg->ticketSize = (uint32_t)ticketSize;
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t ParseNewSessionTicketExtension(TLS_Ctx *ctx, const uint8_t *buf, uint32_t bufLen,
NewSessionTicketMsg *msg)
{
uint32_t bufOffset = 0u;
#ifdef HITLS_TLS_FEATURE_CUSTOM_EXTENSION
uint32_t customExtSeenMask = 0;
#endif
int32_t ret = HITLS_SUCCESS;
while (bufOffset < bufLen) {
uint32_t extMsgLen = 0u;
uint16_t extMsgType = HS_EX_TYPE_END;
ret = ParseExHeader(ctx, &buf[bufOffset], bufLen - bufOffset, &extMsgType, &extMsgLen);
if (ret != HITLS_SUCCESS) {
return ret;
}
bufOffset += HS_EX_HEADER_LEN;
if (bufLen - bufOffset < extMsgLen) {
return HITLS_PARSE_INVALID_MSG_LEN;
}
uint32_t hsExTypeId = HS_GetExtensionTypeId(extMsgType);
#ifdef HITLS_TLS_FEATURE_CUSTOM_EXTENSION
if (hsExTypeId == HS_EX_TYPE_ID_UNRECOGNIZED) {
ret = CheckForDuplicateCustomExtension(ctx, extMsgType, HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET,
&customExtSeenMask, NULL);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#endif
if (hsExTypeId != HS_EX_TYPE_ID_UNRECOGNIZED
#ifdef HITLS_TLS_FEATURE_CUSTOM_EXTENSION
|| !IsParseNeedCustomExtensions(CUSTOM_EXT_FROM_CTX(ctx),
extMsgType, HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET)
#endif
) {
msg->extensionTypeMask |= 1ULL << hsExTypeId;
}
#ifdef HITLS_TLS_FEATURE_CUSTOM_EXTENSION
if (IsParseNeedCustomExtensions(CUSTOM_EXT_FROM_CTX(ctx),
extMsgType, HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET)) {
ret = ParseCustomExtensions(ctx, buf + bufOffset, extMsgType, extMsgLen,
HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET, NULL, 0);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#endif
bufOffset += extMsgLen;
}
if (bufOffset != bufLen) {
return ParseErrorProcess(ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15206,
BINGLOG_STR("parse extension failed."), ALERT_DECODE_ERROR);
}
return HITLS_SUCCESS;
}
static int32_t ParseNewSessionTicketExtensions(ParsePacket *pkt, NewSessionTicketMsg *msg)
{
uint16_t exMsgLen = 0;
int32_t ret = ParseExtensionCommon(pkt, &exMsgLen);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (exMsgLen == 0u) {
return HITLS_SUCCESS;
}
return ParseNewSessionTicketExtension(pkt->ctx, &pkt->buf[*pkt->bufOffset], exMsgLen, msg);
}
#endif
int32_t ParseNewSessionTicket(TLS_Ctx *ctx, const uint8_t *buf, uint32_t bufLen, HS_Msg *hsMsg)
{
uint32_t bufOffset = 0u;
NewSessionTicketMsg *msg = &hsMsg->body.newSessionTicket;
ParsePacket pkt = {.ctx = ctx, .buf = buf, .bufLen = bufLen, .bufOffset = &bufOffset};
const char *logStr = BINGLOG_STR("parse sesionticket len fail.");
int32_t ret = ParseBytesToUint32(&pkt, &msg->ticketLifetimeHint);
if (ret != HITLS_SUCCESS) {
return ParseErrorProcess(pkt.ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID15966, logStr, ALERT_DECODE_ERROR);
}
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
uint32_t ticketAgeAdd = 0;
ret = ParseBytesToUint32(&pkt, &ticketAgeAdd);
if (ret != HITLS_SUCCESS) {
return ParseErrorProcess(pkt.ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16013, logStr, ALERT_DECODE_ERROR);
}
msg->ticketAgeAdd = ticketAgeAdd;
ret = ParseTicketNonce(&pkt, msg);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16014, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"parse ticket nonce failed.", 0, 0, 0, 0);
return ret;
}
}
#endif
ret = ParseTicket(&pkt, msg);
if (ret != HITLS_SUCCESS) {
return ret;
}
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
ret = ParseNewSessionTicketExtensions(&pkt, msg);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17352, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"parse ticket extensions failed.", 0, 0, 0, 0);
return ret;
}
}
#endif
return HITLS_SUCCESS;
}
void CleanNewSessionTicket(NewSessionTicketMsg *msg)
{
if (msg == NULL) {
return;
}
BSL_SAL_FREE(msg->ticketNonce);
BSL_SAL_FREE(msg->ticket);
msg->ticketSize = 0;
msg->ticketNonceSize = 0;
return;
}
#endif