* 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"
#ifdef HITLS_TLS_HOST_CLIENT
#include <stdint.h>
#include <stdbool.h>
#include "bsl_sal.h"
#include <string.h>
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_err_internal.h"
#include "hitls_error.h"
#include "hitls_sni.h"
#include "hitls_security.h"
#include "tls.h"
#ifdef HITLS_TLS_FEATURE_SECURITY
#include "security.h"
#endif
#include "hs.h"
#include "hs_ctx.h"
#include "hs_verify.h"
#include "hs_common.h"
#include "hs_extensions.h"
#include "hs_msg.h"
#include "record.h"
#include "transcript_hash.h"
#include "session_mgr.h"
#include "alpn.h"
#include "alert.h"
#include "hs_kx.h"
#include "config_type.h"
#include "config_check.h"
typedef int32_t (*CheckExtFunc)(TLS_Ctx *ctx, const ServerHelloMsg *serverHello);
static int32_t ClientCheckPointFormats(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((!ctx->hsCtx->extFlag.havePointFormats) && serverHello->havePointFormats) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15255, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get point formats.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
if ((ctx->negotiatedInfo.cipherSuiteInfo.authAlg != HITLS_AUTH_ECDSA) &&
(ctx->negotiatedInfo.cipherSuiteInfo.kxAlg != HITLS_KEY_EXCH_ECDHE) &&
(ctx->negotiatedInfo.cipherSuiteInfo.kxAlg != HITLS_KEY_EXCH_ECDH) &&
(ctx->negotiatedInfo.cipherSuiteInfo.kxAlg != HITLS_KEY_EXCH_ECDHE_PSK)) {
return HITLS_SUCCESS;
}
if (!serverHello->havePointFormats) {
return HITLS_SUCCESS;
}
for (uint8_t i = 0u; i < serverHello->pointFormatsSize; i++) {
if (serverHello->pointFormats[i] == 0u) {
return HITLS_SUCCESS;
}
}
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15256, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"the point format extension in server hello is incorrect.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_POINT_FORMAT);
return HITLS_MSG_HANDLE_UNSUPPORT_POINT_FORMAT;
}
#ifdef HITLS_TLS_FEATURE_ALPN
static int32_t ClientCheckNegotiatedAlpnOfServerHello(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
return ClientCheckNegotiatedAlpn(
ctx, serverHello->haveSelectedAlpn, serverHello->alpnSelected, serverHello->alpnSelectedSize);
}
#endif
#ifdef HITLS_TLS_FEATURE_SNI
static int32_t ClientCheckServerName(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((ctx->hsCtx->extFlag.haveServerName == false) && (serverHello->haveServerName == true)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15263, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send server_name but get extended server_name .", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
if ((ctx->hsCtx->extFlag.haveServerName == true) && (serverHello->haveServerName == true)) {
if (ctx->session == NULL && ctx->config.tlsConfig.serverName != NULL &&
ctx->config.tlsConfig.serverNameSize > 0) {
ctx->negotiatedInfo.isSniStateOK = true;
ctx->negotiatedInfo.serverNameSize = ctx->config.tlsConfig.serverNameSize;
BSL_SAL_FREE(ctx->negotiatedInfo.serverName);
ctx->negotiatedInfo.serverName =
(uint8_t *)BSL_SAL_Dump(ctx->config.tlsConfig.serverName,
ctx->negotiatedInfo.serverNameSize * sizeof(uint8_t));
if (ctx->negotiatedInfo.serverName == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17082, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"Dump fail", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
return HITLS_MEMCPY_FAIL;
}
}
}
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_EXTENDED_MASTER_SECRET
static int32_t ClientCheckExtendedMasterSecret(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((!ctx->hsCtx->extFlag.haveExtendedMasterSecret) && serverHello->haveExtendedMasterSecret) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15264, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get extended master secret.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13 || (ctx->negotiatedInfo.version < HITLS_VERSION_TLS12 &&
ctx->negotiatedInfo.version != HITLS_VERSION_TLCP_DTLCP11)) {
ctx->negotiatedInfo.isExtendedMasterSecret = false;
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_FEATURE_SESSION
If a client receives a ServerHello that accepts an abbreviated
handshake, it behaves as follows:
o If the original session did not use the "extended_master_secret"
extension but the new ServerHello contains the extension, the
client MUST abort the handshake.
o If the original session used the extension but the new ServerHello
does not contain the extension, the client MUST abort the
handshake. */
if (ctx->negotiatedInfo.isResume && ctx->session != NULL) {
bool haveExtMasterSecret = false;
HITLS_SESS_GetHaveExtMasterSecret(ctx->session, &haveExtMasterSecret);
if (serverHello->haveExtendedMasterSecret != haveExtMasterSecret) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17083, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ExtendedMasterSecret err", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_INVALID_EXTENDED_MASTER_SECRET;
}
}
#endif
if (ctx->config.tlsConfig.emsMode == HITLS_EMS_MODE_FORCE && !serverHello->haveExtendedMasterSecret) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17084, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ExtendedMasterSecret err", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_INVALID_EXTENDED_MASTER_SECRET;
}
ctx->negotiatedInfo.isExtendedMasterSecret = (ctx->hsCtx->extFlag.haveExtendedMasterSecret &&
serverHello->haveExtendedMasterSecret);
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t ClientCheckKeyShare(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((!ctx->hsCtx->extFlag.haveKeyShare) && serverHello->haveKeyShare) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15265, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get key share.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
return HITLS_SUCCESS;
}
static int32_t ClientCheckPreShareKey(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((!ctx->hsCtx->extFlag.havePreShareKey) && serverHello->haveSelectedIdentity) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15266, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get pre share key.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
return HITLS_SUCCESS;
}
static int32_t ClientCheckSupportedVersions(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((!ctx->hsCtx->extFlag.haveSupportedVers) && serverHello->haveSupportedVersion) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16133, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get supported versions.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
return HITLS_SUCCESS;
}
#endif
#if defined(HITLS_TLS_PROTO_TLS_BASIC) || defined(HITLS_TLS_PROTO_DTLS12)
static int32_t ClientCheckRenegoInfoDuringFirstHandshake(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (!serverHello->haveSecRenego) {
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
return HITLS_SUCCESS;
}
if (!ctx->config.tlsConfig.allowLegacyRenegotiate) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15899, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"Legacy Renegotiate is not allowed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
return HITLS_SUCCESS;
}
*/
if (serverHello->secRenegoInfoSize != 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15958, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"secRenegoInfoSize should be 0 in client initial handhsake.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
ctx->negotiatedInfo.isSecureRenegotiation = true;
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
static int32_t ClientCheckRenegoInfoDuringRenegotiation(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
const uint8_t *clientData = ctx->negotiatedInfo.clientVerifyData;
uint32_t clientDataSize = ctx->negotiatedInfo.clientVerifyDataSize;
const uint8_t *serverData = ctx->negotiatedInfo.serverVerifyData;
uint32_t serverDataSize = ctx->negotiatedInfo.serverVerifyDataSize;
if (clientData == NULL || serverData == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17085, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "intput null", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return HITLS_NULL_INPUT;
}
if (serverHello->secRenegoInfoSize != (clientDataSize + serverDataSize)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15900, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"secRenegoInfoSize(%u) error, expect %u.", serverHello->secRenegoInfoSize,
(clientDataSize + serverDataSize), 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
if (memcmp(serverHello->secRenegoInfo, clientData, clientDataSize) != 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15901, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"check client secRenegoInfo verify data failed during renegotiation.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
if (memcmp(&serverHello->secRenegoInfo[clientDataSize], serverData, serverDataSize) != 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15902, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"check server secRenegoInfo verify data failed during renegotiation.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
return HITLS_SUCCESS;
}
#endif
static int32_t ClientCheckAndProcessRenegoInfo(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (!ctx->negotiatedInfo.isRenegotiation) {
return ClientCheckRenegoInfoDuringFirstHandshake(ctx, serverHello);
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
return ClientCheckRenegoInfoDuringRenegotiation(ctx, serverHello);
#else
return HITLS_SUCCESS;
#endif
}
#endif
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
static int32_t ClientCheckTicketExternsion(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if ((!ctx->hsCtx->extFlag.haveTicket) && serverHello->haveTicket) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15972, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get ticket externsion.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13 && serverHello->haveTicket) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15912, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"TLS1.3 client get server hello ticket externsion.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
ctx->negotiatedInfo.isTicket = serverHello->haveTicket;
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_ETM
static int32_t ClientCheckEncryptThenMac(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (!ctx->hsCtx->extFlag.haveEncryptThenMac && serverHello->haveEncryptThenMac) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15920, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get encrypt then mac.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
*/
if (!ctx->config.tlsConfig.isEncryptThenMac && serverHello->haveEncryptThenMac) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15931, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client do not support encrypt then mac.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
if (ctx->negotiatedInfo.isRenegotiation && ctx->negotiatedInfo.isEncryptThenMac &&
!serverHello->haveEncryptThenMac) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15934, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"regotiation should not change encrypt then mac to mac then encrypt.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ENCRYPT_THEN_MAC_ERR);
return HITLS_MSG_HANDLE_ENCRYPT_THEN_MAC_ERR;
}
#endif
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
return HITLS_SUCCESS;
}
if (serverHello->haveEncryptThenMac) {
ctx->negotiatedInfo.isEncryptThenMac = true;
} else {
ctx->negotiatedInfo.isEncryptThenMac = false;
}
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_RECORD_SIZE_LIMIT
static int32_t ClientCheckRecordSizeLimit(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (!ctx->hsCtx->extFlag.haveRecordSizeLimit && serverHello->haveRecordSizeLimit) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16251, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client did not send but get record size limit.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNSUPPORTED_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13 && serverHello->haveRecordSizeLimit) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16248, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"tls13 recv record size limit from server hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_PARSE_UNSUPPORTED_EXTENSION);
return HITLS_PARSE_UNSUPPORTED_EXTENSION;
}
ctx->negotiatedInfo.peerRecordSizeLimit = 0;
ctx->negotiatedInfo.recordSizeLimit = 0;
if (serverHello->haveRecordSizeLimit) {
uint16_t upperBound = (GET_VERSION_FROM_CTX(ctx) == HITLS_VERSION_TLS13 ? REC_MAX_PLAIN_LENGTH + 1
: REC_MAX_PLAIN_LENGTH);
if (serverHello->recordSizeLimit < 64u ||
(serverHello->recordSizeLimit > upperBound)) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_INVALID_RECORD_SIZE_LIMIT);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17086, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"The value of record size limit is invalid.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_INVALID_RECORD_SIZE_LIMIT;
}
ctx->negotiatedInfo.recordSizeLimit = (ctx->config.tlsConfig.recordSizeLimit <= upperBound) ?
ctx->config.tlsConfig.recordSizeLimit : upperBound;
ctx->negotiatedInfo.peerRecordSizeLimit = serverHello->recordSizeLimit;
}
return REC_RecOutBufReSet(ctx);
}
#endif
static int32_t ClientCheckExtensionsFlag(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
static const CheckExtFunc extInfoList[] = {
ClientCheckPointFormats,
#ifdef HITLS_TLS_FEATURE_SNI
ClientCheckServerName,
#endif
#ifdef HITLS_TLS_FEATURE_EXTENDED_MASTER_SECRET
ClientCheckExtendedMasterSecret,
#endif
#ifdef HITLS_TLS_FEATURE_ALPN
ClientCheckNegotiatedAlpnOfServerHello,
#endif
#ifdef HITLS_TLS_PROTO_TLS13
ClientCheckKeyShare,
ClientCheckPreShareKey,
ClientCheckSupportedVersions,
#endif
#if defined(HITLS_TLS_PROTO_TLS_BASIC) || defined(HITLS_TLS_PROTO_DTLS12)
ClientCheckAndProcessRenegoInfo,
#endif
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
ClientCheckTicketExternsion,
#endif
#ifdef HITLS_TLS_FEATURE_ETM
ClientCheckEncryptThenMac,
#endif
#ifdef HITLS_TLS_FEATURE_RECORD_SIZE_LIMIT
ClientCheckRecordSizeLimit,
#endif
};
for (uint32_t i = 0; i < sizeof(extInfoList) / sizeof(extInfoList[0]); i++) {
int32_t ret = extInfoList[i](ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
return HITLS_SUCCESS;
}
static bool IsCipherSuiteSupport(const TLS_Ctx *ctx, uint16_t cipherSuite)
{
if (!IsCipherSuiteAllowed(ctx, cipherSuite, true)) {
return false;
}
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
for (uint32_t index = 0; index < ctx->config.tlsConfig.tls13cipherSuitesSize; index++) {
if (cipherSuite == ctx->config.tlsConfig.tls13CipherSuites[index]) {
return true;
}
}
}
#endif
for (uint32_t index = 0; index < ctx->config.tlsConfig.cipherSuitesSize; index++) {
if (cipherSuite == ctx->config.tlsConfig.cipherSuites[index]) {
return true;
}
}
return false;
}
static int32_t ClientCheckCipherSuite(TLS_Ctx *ctx, const ServerHelloMsg *serverHello, bool isHrr)
{
int32_t ret;
(void)isHrr;
if (!IsCipherSuiteSupport(ctx, serverHello->cipherSuite)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15269, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"no supported cipher suites found.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_CIPHER_SUITE_ERR);
return HITLS_MSG_HANDLE_CIPHER_SUITE_ERR;
}
#ifdef HITLS_TLS_PROTO_TLS13
* message is the same as the cipherSuite */
if (!isHrr && ctx->hsCtx->haveHrr) {
if (serverHello->cipherSuite != ctx->negotiatedInfo.cipherSuiteInfo.cipherSuite) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15270, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"cipherSuite in server hello (0x%02x) is defferent from hello retry request (0x%02x).",
serverHello->cipherSuite, ctx->negotiatedInfo.cipherSuiteInfo.cipherSuite, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_CIPHER_SUITE);
return HITLS_MSG_HANDLE_ILLEGAL_CIPHER_SUITE;
}
return HITLS_SUCCESS;
}
#endif
ret = CFG_GetCipherSuiteInfo(serverHello->cipherSuite, &ctx->negotiatedInfo.cipherSuiteInfo);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15271, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"get cipher suite information fail.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
#ifdef HITLS_TLS_FEATURE_SECURITY
ret = SECURITY_SslCheck((HITLS_Ctx *)ctx, HITLS_SECURITY_SECOP_CIPHER_SHARED, 0, 0,
(void *)&ctx->negotiatedInfo.cipherSuiteInfo);
if (ret != SECURITY_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17087, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SslCheck fail, ret %d", ret, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INSUFFICIENT_SECURITY);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSECURE_CIPHER_SUITE);
return HITLS_MSG_HANDLE_UNSECURE_CIPHER_SUITE;
}
#endif
ctx->hsCtx->kxCtx->keyExchAlgo = ctx->negotiatedInfo.cipherSuiteInfo.kxAlg;
BSL_LOG_BINLOG_VARLEN(BINLOG_ID15272, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"ClientCheckCipherSuite: negotiated ciphersuite is [%s].",
ctx->negotiatedInfo.cipherSuiteInfo.name);
return HITLS_SUCCESS;
}
#if defined(HITLS_TLS_PROTO_TLS_BASIC) || defined(HITLS_TLS_PROTO_DTLS12)
static int32_t ClientCheckVersion(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
int32_t ret;
(void)ret;
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
ret = CheckRenegotiatedVersion(ctx);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return RETURN_ALERT_PROCESS(ctx, ret, BINLOG_ID15072,
"The client renegotiation version is inconsistent with the initial one", ALERT_PROTOCOL_VERSION);
}
#endif
uint16_t clientMinVersion = ctx->config.tlsConfig.minVersion;
uint16_t clientMaxVersion = ctx->config.tlsConfig.maxVersion;
uint16_t serverVersion = serverHello->version;
if (IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask)) {
if ((serverVersion > clientMinVersion) || (serverVersion < clientMaxVersion)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15267, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client support version is from %02x to %02x, server selected unsupported version %02x.",
clientMinVersion, clientMaxVersion, serverVersion, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
} else {
if ((serverVersion < clientMinVersion) || (serverVersion > clientMaxVersion)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15268, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client support version is from %02x to %02x, server selected unsupported version %02x.",
clientMinVersion, clientMaxVersion, serverVersion, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
}
#ifdef HITLS_TLS_FEATURE_SECURITY
ret = SECURITY_SslCheck((HITLS_Ctx *)ctx, HITLS_SECURITY_SECOP_VERSION, 0, serverHello->version, NULL);
if (ret != SECURITY_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17088, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SslCheck fail, ret %d", ret, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INSUFFICIENT_SECURITY);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSECURE_VERSION);
return HITLS_MSG_HANDLE_UNSECURE_VERSION;
}
#endif
ctx->negotiatedInfo.version = serverVersion;
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_FEATURE_SESSION
static int32_t ClientCheckResumeServerHello(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
uint16_t version = 0;
uint16_t cipherSuite = 0;
bool haveExtMasterSecret = false;
HITLS_SESS_GetProtocolVersion(ctx->session, &version);
HITLS_SESS_GetCipherSuite(ctx->session, &cipherSuite);
HITLS_SESS_GetHaveExtMasterSecret(ctx->session, &haveExtMasterSecret);
if (serverHello->version != version) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15273, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"the version of resume server hello is different from the pre connect.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_VERSION);
return HITLS_MSG_HANDLE_ILLEGAL_VERSION;
}
if (serverHello->cipherSuite != cipherSuite) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15274, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"the cipher suite of resume server hello is different from the pre connect.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_CIPHER_SUITE);
return HITLS_MSG_HANDLE_ILLEGAL_CIPHER_SUITE;
}
if (serverHello->haveExtendedMasterSecret != haveExtMasterSecret) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15275, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"session resume error:can not downgrade from extended master secret.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_EXTRENED_MASTER_SECRET);
return HITLS_MSG_HANDLE_ILLEGAL_EXTRENED_MASTER_SECRET;
}
return HITLS_SUCCESS;
}
static bool SessionIdCmp(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
HS_Ctx *hsCtx = (HS_Ctx *)ctx->hsCtx;
if ((hsCtx->sessionIdSize == 0u) || (serverHello->sessionIdSize == 0u)) {
return false;
}
if (hsCtx->sessionIdSize != serverHello->sessionIdSize) {
return false;
}
if (memcmp(hsCtx->sessionId, serverHello->sessionId, hsCtx->sessionIdSize) != 0) {
return false;
}
return true;
}
static int32_t ClientCopySessionId(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
HS_Ctx *hsCtx = (HS_Ctx *)ctx->hsCtx;
BSL_SAL_FREE(hsCtx->sessionId);
hsCtx->sessionId = (uint8_t *)BSL_SAL_Calloc(1u, HITLS_SESSION_ID_MAX_SIZE);
if (hsCtx->sessionId == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15276, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"session Id malloc fail.", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
return HITLS_MEMALLOC_FAIL;
}
if (serverHello->sessionIdSize > HITLS_SESSION_ID_MAX_SIZE) {
BSL_SAL_FREE(hsCtx->sessionId);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15277, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"session Id memcpy fail.", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
return HITLS_MEMCPY_FAIL;
}
memcpy(hsCtx->sessionId, serverHello->sessionId, serverHello->sessionIdSize);
hsCtx->sessionIdSize = serverHello->sessionIdSize;
return HITLS_SUCCESS;
}
static int32_t ClientCheckIfResumeFromSession(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
ctx->negotiatedInfo.isResume = false;
if (ctx->session == NULL || serverHello->sessionIdSize == 0u) {
return HITLS_SUCCESS;
}
bool isResume = SessionIdCmp(ctx, serverHello);
if (isResume == true) {
ctx->negotiatedInfo.isResume = true;
return ClientCheckResumeServerHello(ctx, serverHello);
}
return HITLS_SUCCESS;
}
#endif
static int32_t ClientCheckServerHello(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
int32_t ret = ClientCheckVersion(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
memcpy(ctx->hsCtx->serverRandom, serverHello->randomValue, HS_RANDOM_SIZE);
#ifdef HITLS_TLS_FEATURE_SESSION
* extension match */
ret = ClientCheckIfResumeFromSession(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (ctx->negotiatedInfo.isResume == false && serverHello->sessionIdSize > 0) {
ret = ClientCopySessionId(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#endif
ret = ClientCheckCipherSuite(ctx, serverHello, false);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = HS_CheckReceivedExtension(ctx, SERVER_HELLO, serverHello->extensionTypeMask,
HS_EX_TYPE_TLS1_2_ALLOWED_OF_SERVER_HELLO);
if (ret != HITLS_SUCCESS) {
return ret;
}
return ClientCheckExtensionsFlag(ctx, serverHello);
}
int32_t ClientRecvServerHelloProcess(TLS_Ctx *ctx, const HS_Msg *msg)
{
const ServerHelloMsg *serverHello = &msg->body.serverHello;
int32_t ret = ClientCheckServerHello(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = VERIFY_SetHash(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
ctx->hsCtx->verifyCtx, ctx->negotiatedInfo.cipherSuiteInfo.hashAlg);
if (ret != HITLS_SUCCESS) {
return RETURN_ERROR_NUMBER_PROCESS(ret, BINLOG_ID17089, "VERIFY_SetHash fail");
}
#ifdef HITLS_TLS_FEATURE_SESSION
if (ctx->negotiatedInfo.isResume == true) {
ret = HS_ResumeKeyEstablish(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (ctx->negotiatedInfo.isTicket) {
return HS_ChangeState(ctx, TRY_RECV_NEW_SESSION_TICKET);
}
ret = VERIFY_CalcVerifyData(ctx, false, ctx->hsCtx->masterKey, MASTER_SECRET_LEN);
if (ret != HITLS_SUCCESS) {
return RETURN_ALERT_PROCESS(ctx, ret, BINLOG_ID15278,
"client Calculate server finished data error", ALERT_INTERNAL_ERROR);
}
ctx->method.ctrlCCS(ctx, CCS_CMD_RECV_READY);
ctx->method.ctrlCCS(ctx, CCS_CMD_RECV_ACTIVE_CIPHER_SPEC);
return HS_ChangeState(ctx, TRY_RECV_FINISH);
}
#endif
ctx->method.ctrlCCS(ctx, CCS_CMD_RECV_EXIT_READY);
#ifdef HITLS_TLS_FEATURE_PSK
if (!IsNeedCertPrepare(&ctx->negotiatedInfo.cipherSuiteInfo)) {
return HS_ChangeState(ctx, TRY_RECV_SERVER_KEY_EXCHANGE);
}
#endif
return HS_ChangeState(ctx, TRY_RECV_CERTIFICATE);
}
#endif
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t Tls13ClientCheckHelloRetryRequest(TLS_Ctx *ctx, const ServerHelloMsg *helloRetryRequest)
{
if (ctx->hsCtx->haveHrr) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15279, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"duplicate hello retry request.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNEXPECTED_MESSAGE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_DUPLICATE_HELLO_RETYR_REQUEST);
return HITLS_MSG_HANDLE_DUPLICATE_HELLO_RETYR_REQUEST;
}
ctx->hsCtx->haveHrr = true;
if (helloRetryRequest->haveSupportedVersion == false) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15280, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"missing supported version extension in server hello or hello retry request.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_MISSING_EXTENSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_MISSING_EXTENSION);
return HITLS_MSG_HANDLE_MISSING_EXTENSION;
}
if ((helloRetryRequest->haveCookie == false) &&
(helloRetryRequest->haveKeyShare == false)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15281, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"the hello retry reques would not result in any change in the client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_MISSING_EXTENSION);
return HITLS_MSG_HANDLE_MISSING_EXTENSION;
}
return HITLS_SUCCESS;
}
static int32_t Tls13ClientCheckSessionId(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (ctx->hsCtx->sessionIdSize != serverHello->sessionIdSize) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17090, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"sessionIdSize err", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SESSION_ID);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_ILLEGAL_SESSION_ID;
}
if (serverHello->sessionIdSize != 0) {
if (memcmp(ctx->hsCtx->sessionId, serverHello->sessionId, serverHello->sessionIdSize) != 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17091, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"sessionId err", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SESSION_ID);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_ILLEGAL_SESSION_ID;
}
}
return HITLS_SUCCESS;
}
static int32_t Tls13ClientCheckServerHello(TLS_Ctx *ctx, const ServerHelloMsg *serverHello, bool isHrr)
{
memcpy(ctx->hsCtx->serverRandom, serverHello->randomValue, HS_RANDOM_SIZE);
int32_t ret = Tls13ClientCheckSessionId(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
return ClientCheckCipherSuite(ctx, serverHello, isHrr);
}
static bool FindGroupInKeyShare(const TLS_Ctx *ctx, uint16_t selectedGroup)
{
for (size_t i = 0; i < ctx->hsCtx->kxCtx->keyExchParam.share.count; i++) {
if (selectedGroup == ctx->hsCtx->kxCtx->keyExchParam.share.groups[i]) {
return true;
}
}
return false;
}
static int32_t ClientCheckHrrKeyShareExtension(TLS_Ctx *ctx, const ServerHelloMsg *helloRetryRequest)
{
if (helloRetryRequest->haveKeyShare == false) {
return HITLS_SUCCESS;
}
if (helloRetryRequest->keyShare.keyExchangeSize != 0) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID15282,
"the hrr keyshare keyExchangeSize is not 0", ALERT_ILLEGAL_PARAMETER);
}
uint16_t selectedGroup = helloRetryRequest->keyShare.group;
const uint16_t *groups = ctx->config.tlsConfig.groups;
uint32_t numOfGroups = ctx->config.tlsConfig.groupsSize;
if (FindGroupInKeyShare(ctx, selectedGroup)) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID15283,
"hrr selected group in clienthello key share extension", ALERT_ILLEGAL_PARAMETER);
}
bool found = false;
for (uint32_t i = 0; i < numOfGroups; i++) {
if (selectedGroup == groups[i]) {
found = true;
break;
}
}
if (found == false) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID15284,
"selected group not in supported groups", ALERT_ILLEGAL_PARAMETER);
}
#ifdef HITLS_TLS_FEATURE_SECURITY
if (SECURITY_SslCheck(ctx, HITLS_SECURITY_SECOP_CURVE_SUPPORTED, 0, (int32_t)selectedGroup, NULL) !=
SECURITY_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID15284,
"selected group failed security check", ALERT_ILLEGAL_PARAMETER);
}
#endif
ctx->negotiatedInfo.negotiatedGroup = selectedGroup;
return HITLS_SUCCESS;
}
static int32_t ClientCheckHrrCookieExtension(TLS_Ctx *ctx, const ServerHelloMsg *helloRetryRequest)
{
if (helloRetryRequest->haveCookie == false) {
return HITLS_SUCCESS;
}
BSL_SAL_FREE(ctx->negotiatedInfo.cookie);
ctx->negotiatedInfo.cookie = BSL_SAL_Dump(helloRetryRequest->cookie, helloRetryRequest->cookieLen);
if (ctx->negotiatedInfo.cookie == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15285, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"cookie malloc fail when process hello retry request.", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
return HITLS_MEMALLOC_FAIL;
}
ctx->negotiatedInfo.cookieSize = helloRetryRequest->cookieLen;
return HITLS_SUCCESS;
}
static int32_t Tls13ClientCheckHrrExtension(TLS_Ctx *ctx, const ServerHelloMsg *helloRetryRequest)
{
int32_t ret = HS_CheckReceivedExtension(ctx, HELLO_RETRY_REQUEST, helloRetryRequest->extensionTypeMask,
HS_EX_TYPE_TLS1_3_ALLOWED_OF_HELLO_RETRY_REQUEST);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = ClientCheckHrrCookieExtension(ctx, helloRetryRequest);
if (ret != HITLS_SUCCESS) {
return ret;
}
return ClientCheckHrrKeyShareExtension(ctx, helloRetryRequest);
}
int32_t Tls13ClientRecvHelloRetryRequestProcess(TLS_Ctx *ctx, const HS_Msg *msg)
{
const ServerHelloMsg *helloRetryRequest = &msg->body.serverHello;
int32_t ret = Tls13ClientCheckHelloRetryRequest(ctx, helloRetryRequest);
if (ret != HITLS_SUCCESS) {
return ret;
}
* except the extended fields */
ret = Tls13ClientCheckServerHello(ctx, helloRetryRequest, true);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = Tls13ClientCheckHrrExtension(ctx, helloRetryRequest);
if (ret != HITLS_SUCCESS) {
return ret;
}
* constructed */
ret = VERIFY_HelloRetryRequestVerifyProcess(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
return HS_ChangeState(ctx, TRY_SEND_CLIENT_HELLO);
}
#ifdef HITLS_TLS_PROTO_TLS_BASIC
static int32_t CheckDowngradeRandom(TLS_Ctx *ctx, const ServerHelloMsg *serverHello, uint16_t *negotiatedVersion)
{
const uint8_t *downgradeArr = NULL;
uint32_t downgradeArrLen = 0;
if (serverHello->version == HITLS_VERSION_TLS12) {
downgradeArr = HS_GetTls12DowngradeRandom(&downgradeArrLen);
if (memcmp(&serverHello->randomValue[HS_RANDOM_SIZE - downgradeArrLen], downgradeArr, downgradeArrLen) != 0) {
*negotiatedVersion = HITLS_VERSION_TLS12;
return HITLS_SUCCESS;
}
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15286, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"tls1.2 server hello with downgrade random value.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
return HITLS_SUCCESS;
}
#endif
static int32_t GetNegotiatedVersion(TLS_Ctx *ctx, const ServerHelloMsg *serverHello, uint16_t *negotiatedVersion)
{
* extension, the peer end wants to negotiate a version earlier than TLS1.3 */
if (!serverHello->haveSupportedVersion) {
if (serverHello->version < HITLS_VERSION_TLS12) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16169, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client cannot negotiate a version.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
return CheckDowngradeRandom(ctx, serverHello, negotiatedVersion);
}
* legacy_version field must be TLS1.2 */
if (serverHello->version != HITLS_VERSION_TLS12) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15288, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server version error, legacy version is 0x%02x.", serverHello->version, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
* contains a version prior to TLS 1.3, the client MUST abort the handshake with an "illegal_parameter" alert. */
if (serverHello->supportedVersion != HITLS_VERSION_TLS13) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17307, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server version error, selected version is 0x%02x.", serverHello->supportedVersion, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
*negotiatedVersion = HITLS_VERSION_TLS13;
return HITLS_SUCCESS;
}
static int32_t ClientProcessKeyShare(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (serverHello->haveKeyShare == false) {
return HITLS_SUCCESS;
}
uint32_t keyshareLen = 0u;
if (serverHello->keyShare.keyExchangeSize == 0 || serverHello->keyShare.group == HITLS_NAMED_GROUP_BUTT ||
#ifdef HITLS_TLS_FEATURE_SM_TLS13
(IS_SM_TLS13(ctx->negotiatedInfo.cipherSuiteInfo.cipherSuite)
&& serverHello->keyShare.group != HITLS_EC_GROUP_SM2) ||
#endif
(!FindGroupInKeyShare(ctx, serverHello->keyShare.group))) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID15289,
"the keyshare parameter is illegal", ALERT_ILLEGAL_PARAMETER);
}
const KeyShare *keyShare = &serverHello->keyShare;
for (size_t i = 0; i < ctx->hsCtx->kxCtx->keyExchParam.share.count; i++) {
if (keyShare->group == ctx->hsCtx->kxCtx->keyExchParam.share.groups[i]) {
SAL_CRYPT_FreeEcdhKey(ctx->hsCtx->kxCtx->key);
ctx->hsCtx->kxCtx->key = ctx->hsCtx->kxCtx->keys[i];
ctx->hsCtx->kxCtx->keys[i] = NULL;
ctx->hsCtx->kxCtx->keyExchParam.share.groups[0] = keyShare->group;
ctx->hsCtx->kxCtx->keyExchParam.share.count = 1;
break;
}
}
const TLS_GroupInfo *groupInfo = ConfigGetGroupInfo(&ctx->config.tlsConfig, keyShare->group);
if (groupInfo == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_INVALID_INPUT, BINLOG_ID16247, "group info not found");
}
if (groupInfo->isKem) {
keyshareLen = groupInfo->ciphertextLen;
} else {
keyshareLen = groupInfo->pubkeyLen;
}
if (keyshareLen == 0u || keyshareLen != keyShare->keyExchangeSize) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17326, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"invalid keyShare length [%d]", keyShare->keyExchangeSize, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP;
}
uint8_t *peerPubkey = BSL_SAL_Dump(keyShare->keyExchange, keyshareLen);
if (peerPubkey == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
return RETURN_ALERT_PROCESS(ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID15290,
"malloc peerPubkey fail when process server hello key share", ALERT_INTERNAL_ERROR);
}
BSL_SAL_FREE(ctx->hsCtx->kxCtx->peerPubkey);
ctx->hsCtx->kxCtx->peerPubkey = peerPubkey;
ctx->hsCtx->kxCtx->pubKeyLen = keyshareLen;
ctx->negotiatedInfo.negotiatedGroup = serverHello->keyShare.group;
return HITLS_SUCCESS;
}
static int32_t ClientProcessPreSharedKey(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
if (serverHello->haveSelectedIdentity == false) {
return HITLS_SUCCESS;
}
PskInfo13 *pskInfo = &ctx->hsCtx->kxCtx->pskInfo13;
HITLS_Session *pskSession = NULL;
bool isResumePsk = false;
BSL_SAL_ClearFree(pskInfo->psk, pskInfo->pskLen);
pskInfo->psk = NULL;
if (pskInfo->resumeSession != NULL && serverHello->selectedIdentity == 0) {
pskSession = pskInfo->resumeSession;
isResumePsk = true;
} else if (pskInfo->userPskSess == NULL || serverHello->selectedIdentity != pskInfo->userPskSess->num) {
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_PSK_IDENTITY);
return HITLS_MSG_HANDLE_ILLEGAL_PSK_IDENTITY;
} else {
pskSession = pskInfo->userPskSess->pskSession;
}
pskInfo->selectIndex = serverHello->selectedIdentity;
uint8_t psk[HS_PSK_MAX_LEN] = {0};
uint32_t pskLen = HS_PSK_MAX_LEN;
uint16_t cipherSuite = 0;
HITLS_SESS_GetCipherSuite(pskSession, &cipherSuite);
CipherSuiteInfo cipherInfo = {0};
int32_t ret = CFG_GetCipherSuiteInfo(cipherSuite, &cipherInfo);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
return RETURN_ALERT_PROCESS(ctx, ret, BINLOG_ID17093, "GetCipherSuiteInfo fail", ALERT_INTERNAL_ERROR);
}
if (cipherInfo.hashAlg != ctx->negotiatedInfo.cipherSuiteInfo.hashAlg) {
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_PSK_SESSION_INVALID_CIPHER_SUITE);
return HITLS_MSG_HANDLE_PSK_SESSION_INVALID_CIPHER_SUITE;
}
ret = HITLS_SESS_GetMasterKey(pskSession, psk, &pskLen);
if (ret != HITLS_SUCCESS) {
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return ret;
}
pskInfo->psk = BSL_SAL_Dump(psk, pskLen);
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
if (pskInfo->psk == NULL) {
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
return RETURN_ALERT_PROCESS(ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID17094, "dump psk fail", ALERT_INTERNAL_ERROR);
}
pskInfo->pskLen = pskLen;
ctx->negotiatedInfo.isResume = isResumePsk;
return HITLS_SUCCESS;
}
static uint32_t GetServertls13AuthType(const ServerHelloMsg *serverHello)
{
uint32_t tls13BasicKeyExMode = 0;
if (serverHello->haveKeyShare && serverHello->haveSelectedIdentity) {
tls13BasicKeyExMode = TLS13_KE_MODE_PSK_WITH_DHE;
} else if (serverHello->haveSelectedIdentity) {
tls13BasicKeyExMode = TLS13_KE_MODE_PSK_ONLY;
} else if (serverHello->haveKeyShare) {
tls13BasicKeyExMode = TLS13_CERT_AUTH_WITH_DHE;
}
return tls13BasicKeyExMode;
}
static int32_t Tls13ProcessServerHelloExtension(TLS_Ctx *ctx, const ServerHelloMsg *serverHello)
{
int32_t ret = HS_CheckReceivedExtension(ctx, SERVER_HELLO, serverHello->extensionTypeMask,
HS_EX_TYPE_TLS1_3_ALLOWED_OF_SERVER_HELLO);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = ClientCheckExtensionsFlag(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
uint32_t tls13BasicKeyExMode = GetServertls13AuthType(serverHello) & ctx->negotiatedInfo.tls13BasicKeyExMode;
if (tls13BasicKeyExMode == 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16141, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server selects the mode in which the client does not send.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_HANDSHAKE_FAILURE;
}
ctx->negotiatedInfo.tls13BasicKeyExMode = tls13BasicKeyExMode;
ret = ClientProcessKeyShare(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
return ClientProcessPreSharedKey(ctx, serverHello);
}
int32_t Tls13ProcessServerHello(TLS_Ctx *ctx, const HS_Msg *msg)
{
const ServerHelloMsg *serverHello = &msg->body.serverHello;
int32_t ret = Tls13ClientCheckServerHello(ctx, serverHello, false);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = Tls13ProcessServerHelloExtension(ctx, serverHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = VERIFY_SetHash(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
ctx->hsCtx->verifyCtx, ctx->negotiatedInfo.cipherSuiteInfo.hashAlg);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = HS_TLS13CalcServerHelloProcessSecret(ctx);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17095, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"CalcServerHelloProcessSecret fail", 0, 0, 0, 0);
return ret;
}
ret = HS_TLS13DeriveHandshakeTrafficSecret(ctx);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17096, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"DeriveHandshakeTrafficSecret fail", 0, 0, 0, 0);
return ret;
}
uint32_t hashLen = SAL_CRYPT_DigestSize(ctx->negotiatedInfo.cipherSuiteInfo.hashAlg);
if (hashLen == 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17097, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "DigestSize err", 0, 0, 0, 0);
return HITLS_CRYPT_ERR_DIGEST;
}
ret = HS_SwitchTrafficKey(ctx, ctx->hsCtx->serverHsTrafficSecret, hashLen, false);
if (ret != HITLS_SUCCESS) {
return ret;
}
return HS_ChangeState(ctx, TRY_RECV_ENCRYPTED_EXTENSIONS);
}
int32_t Tls13ClientRecvServerHelloProcess(TLS_Ctx *ctx, const HS_Msg *msg)
{
const ServerHelloMsg *serverHello = &msg->body.serverHello;
uint16_t negotiatedVersion = 0;
int32_t ret = GetNegotiatedVersion(ctx, serverHello, &negotiatedVersion);
if (ret != HITLS_SUCCESS) {
return ret;
}
#ifdef HITLS_TLS_PROTO_TLS_BASIC
if (negotiatedVersion < HITLS_VERSION_TLS13) {
* here first */
HS_KeyExchCtxFree(ctx->hsCtx->kxCtx);
ctx->hsCtx->kxCtx = HS_KeyExchCtxNew();
if (ctx->hsCtx->kxCtx == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17098, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"KeyExchCtxNew fail", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
return HITLS_MEMALLOC_FAIL;
}
return ClientRecvServerHelloProcess(ctx, msg);
}
#endif
ctx->negotiatedInfo.version = negotiatedVersion;
uint32_t hrrRandomSize = 0;
const uint8_t *hrrRandom = HS_GetHrrRandom(&hrrRandomSize);
if (memcmp(serverHello->randomValue, hrrRandom, hrrRandomSize) == 0) {
return Tls13ClientRecvHelloRetryRequestProcess(ctx, msg);
}
return Tls13ProcessServerHello(ctx, msg);
}
#endif
#endif