* 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_SERVER
#include "tls.h"
#include <string.h>
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_sal.h"
#include "bsl_err_internal.h"
#include "hitls.h"
#include "hitls_error.h"
#include "hitls_sni.h"
#include "hitls_alpn.h"
#include "hitls_security.h"
#include "bsl_uio.h"
#include "alert.h"
#include "session_mgr.h"
#include "recv_process.h"
#include "config_check.h"
#ifdef HITLS_TLS_FEATURE_SECURITY
#include "security.h"
#endif
#include "sni.h"
#include "hs_ctx.h"
#include "hs.h"
#include "hs_common.h"
#include "hs_extensions.h"
#include "hs_verify.h"
#include "hs_cert.h"
#include "record.h"
#include "hs_cookie.h"
#ifdef HITLS_TLS_FEATURE_SESSION
#include "session_mgr.h"
#endif
#include "bsl_bytes.h"
#include "cert_method.h"
#ifdef HITLS_TLS_PROTO_TLS13
#if defined(HITLS_TLS_FEATURE_SESSION) || defined(HITLS_TLS_FEATURE_PSK)
#define HS_MAX_BINDER_SIZE 64
#endif
#endif
#ifdef HITLS_TLS_SUITE_KX_ECDHE
* @brief Check the extension of the client hello point format.
*
* @param clientHello [IN] client hello packet
*
* @retval HITLS_SUCCESS succeeded.
* @retval HITLS_MSG_HANDLE_UNSUPPORT_POINT_FORMAT Unsupported point format
*/
static int32_t ServerCheckPointFormats(const ClientHelloMsg *clientHello)
{
if (!clientHello->extension.flag.havePointFormats) {
return HITLS_SUCCESS;
}
for (uint32_t i = 0u; i < clientHello->extension.content.pointFormatsSize; i++) {
if (clientHello->extension.content.pointFormats[i] == 0u) {
return HITLS_SUCCESS;
}
}
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_POINT_FORMAT);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15210, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"the point format extension in client hello is unsupported.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_UNSUPPORT_POINT_FORMAT;
}
static void BuildTupleGroupsArray(const TLS_Ctx *ctx, uint32_t tupleStartIdx, uint32_t tupleSize, uint16_t *tupleGroups,
uint32_t *tupleGroupCount)
{
const TLS_Config *config = &ctx->config.tlsConfig;
*tupleGroupCount = 0;
for (uint32_t i = 0; i < tupleSize && (tupleStartIdx + i) < config->groupsSize; i++) {
uint16_t group = config->groups[tupleStartIdx + i];
if (!GroupConformToVersion(ctx, ctx->negotiatedInfo.version, group)) {
continue;
}
#ifdef HITLS_TLS_FEATURE_SM_TLS13
if (IS_SM_TLS13(ctx->negotiatedInfo.cipherSuiteInfo.cipherSuite) && group != HITLS_EC_GROUP_SM2) {
continue;
}
#endif
tupleGroups[(*tupleGroupCount)++] = group;
}
}
static uint16_t ClientPrefSelectByTuple(const ClientHelloMsg *clientHello, const uint16_t *tupleGroups,
uint32_t tupleGroupCount)
{
KeyShare *clientKeyShares = clientHello->extension.content.keyShare;
const uint16_t *clientSupportedGroups = clientHello->extension.content.supportedGroups;
uint32_t clientSupportedGroupsSize = clientHello->extension.content.supportedGroupsSize;
ListHead *node = NULL;
ListHead *tmpNode = NULL;
KeyShare *cur = NULL;
uint32_t i;
uint32_t clientIdx;
uint16_t clientKeyshareGroup;
uint16_t clientSupportedGroup;
if (clientKeyShares == NULL) {
goto CHECK_SUPPORTED_GROUP;
}
LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(clientKeyShares->head)) {
cur = BSL_LIST_ENTRY(node, KeyShare, head);
clientKeyshareGroup = cur->group;
for (i = 0; i < tupleGroupCount; i++) {
if (clientKeyshareGroup == tupleGroups[i]) {
return clientKeyshareGroup;
}
}
}
CHECK_SUPPORTED_GROUP:
for (clientIdx = 0; clientIdx < clientSupportedGroupsSize; clientIdx++) {
clientSupportedGroup = clientSupportedGroups[clientIdx];
for (i = 0; i < tupleGroupCount; i++) {
if (clientSupportedGroup == tupleGroups[i]) {
return clientSupportedGroup;
}
}
}
return HITLS_NAMED_GROUP_BUTT;
}
static uint16_t ServerPrefSelectByTuple(const ClientHelloMsg *clientHello, const uint16_t *tupleGroups,
uint32_t tupleGroupCount)
{
KeyShare *clientKeyShares = clientHello->extension.content.keyShare;
const uint16_t *clientSupportedGroups = clientHello->extension.content.supportedGroups;
uint32_t clientSupportedGroupsSize = clientHello->extension.content.supportedGroupsSize;
ListHead *node = NULL;
ListHead *tmpNode = NULL;
KeyShare *cur = NULL;
uint32_t i;
uint32_t clientIdx;
uint16_t serverGroup;
if (clientKeyShares == NULL) {
goto CHECK_SUPPORTED_GROUP;
}
for (i = 0; i < tupleGroupCount; i++) {
serverGroup = tupleGroups[i];
LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(clientKeyShares->head)) {
cur = BSL_LIST_ENTRY(node, KeyShare, head);
if (cur->group == serverGroup) {
return serverGroup;
}
}
}
CHECK_SUPPORTED_GROUP:
for (i = 0; i < tupleGroupCount; i++) {
serverGroup = tupleGroups[i];
for (clientIdx = 0; clientIdx < clientSupportedGroupsSize; clientIdx++) {
if (serverGroup == clientSupportedGroups[clientIdx]) {
return serverGroup;
}
}
}
return HITLS_NAMED_GROUP_BUTT;
}
static uint16_t ServerSelectCurveId(const TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
const TLS_Config *config = &ctx->config.tlsConfig;
uint32_t tempTuples[1] = {config->groupsSize};
uint32_t tempTuplesSize = 1;
const uint32_t *tuples = config->tuples == NULL ? tempTuples : config->tuples;
const uint32_t tupleCount = config->tuples == NULL ? tempTuplesSize : config->tuplesSize;
uint16_t *tupleGroups = NULL;
uint32_t tupleGroupsCapacity = 0;
bool serverPrefer = false;
#ifdef HITLS_TLS_PROTO_DFX_SERVER_PREFER
serverPrefer = config->isSupportServerPreference;
#endif
uint32_t currentTupleStartIdx = 0;
for (uint32_t tupleIdx = 0; tupleIdx < tupleCount; tupleIdx++) {
uint32_t tupleSize = tuples[tupleIdx];
uint32_t tupleGroupCount = 0;
if (tupleSize > tupleGroupsCapacity) {
uint16_t *newTupleGroups = BSL_SAL_Realloc(tupleGroups, tupleSize * sizeof(uint16_t),
tupleGroupsCapacity * sizeof(uint16_t));
if (newTupleGroups == NULL) {
BSL_SAL_FREE(tupleGroups);
return HITLS_NAMED_GROUP_BUTT;
}
tupleGroups = newTupleGroups;
tupleGroupsCapacity = tupleSize;
}
BuildTupleGroupsArray(ctx, currentTupleStartIdx, tupleSize, tupleGroups, &tupleGroupCount);
if (tupleGroupCount == 0) {
currentTupleStartIdx += tupleSize;
continue;
}
uint16_t selectedGroup = 0;
if (!serverPrefer) {
selectedGroup = ClientPrefSelectByTuple(clientHello, tupleGroups, tupleGroupCount);
} else {
selectedGroup = ServerPrefSelectByTuple(clientHello, tupleGroups, tupleGroupCount);
}
if (selectedGroup != HITLS_NAMED_GROUP_BUTT) {
BSL_SAL_FREE(tupleGroups);
return selectedGroup;
}
currentTupleStartIdx += tupleSize;
}
BSL_SAL_FREE(tupleGroups);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15211, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"No supported group found in tuple configuration.", 0, 0, 0, 0);
return HITLS_NAMED_GROUP_BUTT;
}
#endif
* @brief Select a proper certificate based on the TLS cipher suite.
*
* @param ctx [IN] TLS context
* @param clientHello [IN] Client Hello packet
* @param cipherInfo [IN] TLS cipher suite
*
* @retval HITLS_SUCCESS succeeded.
* @retval HITLS_MEMALLOC_FAIL Memory application failed.
*/
static int32_t HsServerSelectCert(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, const CipherSuiteInfo *cipherInfo)
{
uint16_t signHashAlgo = cipherInfo->signScheme;
CERT_ExpectInfo expectCertInfo = {0};
expectCertInfo.certType = CFG_GetCertTypeByCipherSuite(cipherInfo->cipherSuite);
if (clientHello->extension.content.signatureAlgorithms != NULL &&
(ctx->negotiatedInfo.version != HITLS_VERSION_TLCP_DTLCP11)) {
expectCertInfo.signSchemeList = clientHello->extension.content.signatureAlgorithms;
expectCertInfo.signSchemeNum = clientHello->extension.content.signatureAlgorithmsSize;
} else {
expectCertInfo.signSchemeList = &signHashAlgo;
expectCertInfo.signSchemeNum = 1u;
}
expectCertInfo.ellipticCurveList = clientHello->extension.content.supportedGroups;
expectCertInfo.ellipticCurveNum = clientHello->extension.content.supportedGroupsSize;
uint8_t pointFormat = HITLS_POINT_FORMAT_UNCOMPRESSED;
expectCertInfo.ecPointFormatList = &pointFormat;
expectCertInfo.ecPointFormatNum = 1u;
return HS_SelectCertByInfo(ctx, &expectCertInfo);
}
#ifdef HITLS_TLS_SUITE_KX_ECDHE
#ifdef HITLS_TLS_PROTO_TLCP11
static bool CheckLocalContainCurveType(const uint16_t *groups, uint32_t groupsSize, uint16_t exp)
{
for (uint32_t i = 0; i < groupsSize; ++i) {
if (groups[i] == exp) {
return true;
}
}
return false;
}
#endif
* @brief Process the ECDHE cipher suite.
*
* @param ctx [IN] TLS context
* @param clientHello [IN] Client Hello packet
* @param cipherSuiteInfo [OUT] Cipher suite information
*
* @retval HITLS_SUCCESS succeeded.
* @retval HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE Unsupported cipher suites
*/
static int32_t ProcessEcdheCipherSuite(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if ((ctx->config.tlsConfig.groupsSize == 0u) || (ctx->config.tlsConfig.groups == NULL)) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE, BINLOG_ID15212,
"can not used ecdhe whitout curve id");
}
#ifdef HITLS_TLS_PROTO_TLCP11
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLCP_DTLCP11) {
if (CheckLocalContainCurveType(ctx->config.tlsConfig.groups,
ctx->config.tlsConfig.groupsSize, HITLS_EC_GROUP_SM2) != true) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE, BINLOG_ID16231,
"TLCP need sm2 curve");
}
ctx->hsCtx->kxCtx->keyExchParam.ecdh.curveParams.type = HITLS_EC_CURVE_TYPE_NAMED_CURVE;
ctx->hsCtx->kxCtx->keyExchParam.ecdh.curveParams.param.namedcurve = HITLS_EC_GROUP_SM2;
return HITLS_SUCCESS;
}
#endif
int32_t ret = ServerCheckPointFormats(clientHello);
if (ret != HITLS_SUCCESS) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE, BINLOG_ID15213,
"server check client hello point formats fail");
}
uint16_t selectedEcCurveId =
#ifdef HITLS_TLS_PROTO_TLS13
ctx->hsCtx->haveHrr ? ctx->negotiatedInfo.negotiatedGroup :
#endif
ServerSelectCurveId(ctx, clientHello);
if (selectedEcCurveId == HITLS_NAMED_GROUP_BUTT) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE, BINLOG_ID15214,
"server select curve id fail");
}
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
ctx->hsCtx->kxCtx->keyExchParam.share.groups[0] = selectedEcCurveId;
ctx->hsCtx->kxCtx->keyExchParam.share.count = 1;
} else
#endif
{
ctx->hsCtx->kxCtx->keyExchParam.ecdh.curveParams.type = HITLS_EC_CURVE_TYPE_NAMED_CURVE;
ctx->hsCtx->kxCtx->keyExchParam.ecdh.curveParams.param.namedcurve = selectedEcCurveId;
}
ctx->negotiatedInfo.negotiatedGroup = selectedEcCurveId;
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_CONFIG_MANUAL_DH
static bool IsDHEAvailable(TLS_Ctx *ctx)
{
return ctx->config.tlsConfig.isSupportDhAuto || ctx->config.tlsConfig.dhTmpCb != NULL ||
ctx->config.tlsConfig.dhTmp != NULL;
}
#endif
* @brief Check whether the server supports the cipher suite.
*
* @param ctx [IN] TLS context
* @param clientHello [IN] client hello packet
* @param cipher [IN] cipher suite ID
*
* @retval HITLS_SUCCESS succeeded.
* @retval HITLS_MEMCPY_FAIL Memory Copy Failure
* @retval HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE Unsupported cipher suites
*/
static int32_t ServerNegotiateCipher(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, uint16_t cipher)
{
CipherSuiteInfo cipherSuiteInfo = {0};
int32_t ret = CFG_GetCipherSuiteInfo(cipher, &cipherSuiteInfo);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15215, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"get cipher suite info fail when processing client hello.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE;
}
if (IsNeedCertPrepare(&cipherSuiteInfo) == true) {
if (HsServerSelectCert(ctx, clientHello, &cipherSuiteInfo) != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15216, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"have no suitable cert.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_ERR_NO_SERVER_CERTIFICATE;
}
}
switch (cipherSuiteInfo.kxAlg) {
#ifdef HITLS_TLS_SUITE_KX_ECDHE
case HITLS_KEY_EXCH_ECDHE:
case HITLS_KEY_EXCH_ECDHE_PSK:
ret = ProcessEcdheCipherSuite(ctx, clientHello);
break;
#endif
case HITLS_KEY_EXCH_DHE:
case HITLS_KEY_EXCH_DHE_PSK:
#ifdef HITLS_TLS_CONFIG_MANUAL_DH
ret = IsDHEAvailable(ctx) ? HITLS_SUCCESS : HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE;
break;
#endif
case HITLS_KEY_EXCH_RSA:
#ifdef HITLS_TLS_PROTO_TLCP11
case HITLS_KEY_EXCH_ECC:
#endif
case HITLS_KEY_EXCH_PSK:
case HITLS_KEY_EXCH_RSA_PSK:
ret = HITLS_SUCCESS;
break;
default:
ret = HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE;
}
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15217, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"server process ecdhe cipher suite fail. kxAlg is %d", cipherSuiteInfo.kxAlg, 0, 0, 0);
return ret;
}
ctx->hsCtx->kxCtx->keyExchAlgo = cipherSuiteInfo.kxAlg;
memcpy(&ctx->negotiatedInfo.cipherSuiteInfo, &cipherSuiteInfo, sizeof(CipherSuiteInfo));
return ret;
}
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t Tls13ServerNegotiateCipher(TLS_Ctx *ctx, uint16_t cipher, bool preferSha256)
{
int32_t ret = 0;
CipherSuiteInfo cipherSuiteInfo = {0};
ret = CFG_GetCipherSuiteInfo(cipher, &cipherSuiteInfo);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15218, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"get cipher suite info fail when processing client hello.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_UNSUPPORT_CIPHER_SUITE;
}
cipher suite. */
if (preferSha256 && cipherSuiteInfo.hashAlg != HITLS_HASH_SHA_256) {
return HITLS_CONFIG_NO_SUITABLE_CIPHER_SUITE;
}
#ifdef HITLS_TLS_FEATURE_SM_TLS13
if (IS_SM_TLS13(cipher)) {
int32_t certKeyType = TLS_CERT_KEY_TYPE_SM2;
CERT_MgrCtx *mgrCtx = ctx->config.tlsConfig.certMgrCtx;
if (mgrCtx == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_CONFIG_NO_SUITABLE_CIPHER_SUITE);
return HITLS_CONFIG_NO_SUITABLE_CIPHER_SUITE;
}
CERT_Pair *certPair = NULL;
ret = BSL_HASH_At(mgrCtx->certPairs, (uintptr_t)certKeyType, (uintptr_t *)&certPair);
if (ret != HITLS_SUCCESS || certPair == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSECURE_CIPHER_SUITE);
return HITLS_MSG_HANDLE_UNSECURE_CIPHER_SUITE;
}
HITLS_Config *config = &ctx->config.tlsConfig;
int32_t signAlg = 0;
ret = SAL_CERT_X509Ctrl(config, certPair->cert, CERT_CTRL_GET_SIGN_ALGO, NULL, (void *)&signAlg);
if (ret != HITLS_SUCCESS || signAlg != CERT_SIG_SCHEME_SM2_SM3) {
BSL_ERR_PUSH_ERROR(HITLS_CERT_ERR_NO_SIGN_SCHEME_MATCH);
return HITLS_CERT_ERR_NO_SIGN_SCHEME_MATCH;
}
bool checkUsageRec = SAL_CERT_CheckCertKeyUsage(ctx, certPair->cert, CERT_KEY_CTRL_IS_DIGITAL_SIGN_USAGE);
if (!checkUsageRec) {
BSL_ERR_PUSH_ERROR(HITLS_CERT_ERR_KEYUSAGE);
return HITLS_CERT_ERR_KEYUSAGE;
}
}
#endif
memcpy(&ctx->negotiatedInfo.cipherSuiteInfo, &cipherSuiteInfo, sizeof(CipherSuiteInfo));
return HITLS_SUCCESS;
}
#endif
static int32_t CheckCipherSuite(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, uint16_t cipherSuite,
bool preferSha256)
{
(void)preferSha256;
if (!IsCipherSuiteAllowed(ctx, cipherSuite, true)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17046, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"No proper cipher suite", 0, 0, 0, 0);
return HITLS_CONFIG_UNSUPPORT_CIPHER_SUITE;
}
int32_t ret = 0;
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
ret = Tls13ServerNegotiateCipher(ctx, cipherSuite, preferSha256);
} else
#endif
{
ret = ServerNegotiateCipher(ctx, clientHello, cipherSuite);
}
if (ret != HITLS_SUCCESS) {
return ret;
}
#if defined(HITLS_BSL_LOG) || defined(HITLS_TLS_FEATURE_SECURITY)
CipherSuiteInfo *cipherSuiteInfo = &ctx->negotiatedInfo.cipherSuiteInfo;
#endif
#ifdef HITLS_TLS_FEATURE_SECURITY
ret = SECURITY_SslCheck((HITLS_Ctx *)ctx, HITLS_SECURITY_SECOP_CIPHER_SHARED, 0, 0, (void *)cipherSuiteInfo);
if (ret != SECURITY_SUCCESS) {
ctx->hsCtx->kxCtx->keyExchAlgo = HITLS_KEY_EXCH_NULL;
BSL_SAL_CleanseData(&ctx->hsCtx->kxCtx->keyExchParam, sizeof(ctx->hsCtx->kxCtx->keyExchParam));
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17047, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SslCheck fail, ret %d", ret, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSECURE_CIPHER_SUITE);
return HITLS_MSG_HANDLE_UNSECURE_CIPHER_SUITE;
}
#endif
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15221, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN, "chosen ciphersuite 0x%04x",
cipherSuiteInfo->cipherSuite, 0, 0, 0);
BSL_LOG_BINLOG_VARLEN(BINLOG_ID15894, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN, "chosen ciphersuite: %s",
cipherSuiteInfo->name);
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_PROTO_TLS13
static bool Tls13HasCertificate(TLS_Ctx *ctx)
{
CERT_MgrCtx *certMgrCtx = ctx->config.tlsConfig.certMgrCtx;
if (certMgrCtx == NULL) {
return false;
}
BSL_HASH_Hash *certPairs = certMgrCtx->certPairs;
BSL_HASH_Iterator it = BSL_HASH_IterBegin(certPairs);
while (it != BSL_HASH_IterEnd(certPairs)) {
uint32_t keyType = (uint32_t)BSL_HASH_HashIterKey(certPairs, it);
if (keyType == TLS_CERT_KEY_TYPE_DSA) {
it = BSL_HASH_IterNext(certPairs, it);
continue;
}
uintptr_t ptr = BSL_HASH_IterValue(certPairs, it);
CERT_Pair *certPair = (CERT_Pair *)ptr;
if (certPair != NULL && certPair->cert != NULL && certPair->privateKey != NULL) {
return true;
}
it = BSL_HASH_IterNext(certPairs, it);
}
return false;
}
#endif
int32_t ServerSelectCipherSuite(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
uint16_t *cfgCipherSuites = ctx->config.tlsConfig.cipherSuites;
uint32_t cfgCipherSuitesSize = ctx->config.tlsConfig.cipherSuitesSize;
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
cfgCipherSuites = ctx->config.tlsConfig.tls13CipherSuites;
cfgCipherSuitesSize = ctx->config.tlsConfig.tls13cipherSuitesSize;
}
#endif
const uint16_t *preferenceCipherSuites = clientHello->cipherSuites;
uint16_t preferenceCipherSuitesSize = clientHello->cipherSuitesSize;
const uint16_t *normalCipherSuites = cfgCipherSuites;
uint16_t normalCipherSuitesSize = (uint16_t)cfgCipherSuitesSize;
#ifdef HITLS_TLS_PROTO_DFX_SERVER_PREFER
if (ctx->config.tlsConfig.isSupportServerPreference) {
preferenceCipherSuites = cfgCipherSuites;
preferenceCipherSuitesSize = (uint16_t)cfgCipherSuitesSize;
normalCipherSuites = clientHello->cipherSuites;
normalCipherSuitesSize = clientHello->cipherSuitesSize;
}
#endif
bool preferSha256 = false;
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13 && ctx->config.tlsConfig.pskServerCb != NULL) {
preferSha256 = !Tls13HasCertificate(ctx);
}
#endif
for (uint16_t i = 0u; i < preferenceCipherSuitesSize; i++) {
for (uint32_t j = 0u; j < normalCipherSuitesSize; j++) {
if (normalCipherSuites[j] != preferenceCipherSuites[i]) {
continue;
}
if (CheckCipherSuite(ctx, clientHello, normalCipherSuites[j], preferSha256) != HITLS_SUCCESS) {
break;
}
return HITLS_SUCCESS;
}
}
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_CIPHER_SUITE_ERR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15222, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"can not find a appropriate cipher suite.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_CIPHER_SUITE_ERR;
}
#if defined(HITLS_TLS_PROTO_TLS_BASIC) || defined(HITLS_TLS_PROTO_DTLS12)
static uint32_t MapLegacyVersionToBits(const TLS_Ctx *ctx, uint16_t version)
{
uint32_t ret = 0;
if (version >= HITLS_VERSION_TLCP_DTLCP11 && version < HITLS_VERSION_SSL30) {
ret = (ctx->config.tlsConfig.originVersionMask & TLCP_VERSION_BITS);
return ret;
}
uint16_t versions[] = {HITLS_VERSION_DTLS12, HITLS_VERSION_TLS12};
bool isGreater = !IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask);
for (uint32_t i = 0; i < sizeof(versions) / sizeof(versions[0]); i++) {
if (isGreater? version >= versions[i] : version <= versions[i]) {
ret |= MapVersion2VersionBit(IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask), versions[i]);
}
}
return ret;
}
* @brief Select the negotiation version based on the client Hello packet.
*
* @param ctx [IN] TLS context
* @param clientHello [IN] client Hello packet
*
* @retval HITLS_SUCCESS succeeded.
* @retval HITLS_MSG_HANDLE_UNSUPPORT_VERSION Unsupported version number
*/
static int32_t ServerSelectNegoVersion(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret = HITLS_SUCCESS;
(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_ID15071,
"The server renegotiation version is inconsistent with the initial one", ALERT_PROTOCOL_VERSION);
}
#endif
uint16_t legacyVersion = clientHello->version;
uint32_t legacyVersionBits = MapLegacyVersionToBits(ctx, legacyVersion);
uint32_t intersection = ctx->config.tlsConfig.version & legacyVersionBits;
if (intersection == 0) {
if (TLS_IS_FIRST_HANDSHAKE(ctx)) {
ctx->negotiatedInfo.version = legacyVersion;
}
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15220, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client want a unsupported protocol version 0x%02x.", legacyVersion, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
uint16_t versions[] = {HITLS_VERSION_DTLS12, HITLS_VERSION_TLS12, HITLS_VERSION_TLCP_DTLCP11,
HITLS_VERSION_TLCP_DTLCP11};
uint32_t versionBits[] = {DTLS12_VERSION_BIT, TLS12_VERSION_BIT, TLCP11_VERSION_BIT,
DTLCP11_VERSION_BIT};
for (uint32_t i = 0; i < sizeof(versionBits) / sizeof(versionBits[0]); i++) {
if (intersection & versionBits[i]) {
ctx->negotiatedInfo.version = versions[i];
break;
}
}
#ifdef HITLS_TLS_FEATURE_SECURITY
ret = SECURITY_SslCheck((HITLS_Ctx *)ctx, HITLS_SECURITY_SECOP_VERSION, 0, ctx->negotiatedInfo.version, NULL);
if (ret != SECURITY_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSECURE_VERSION);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_UNSECURE_VERSION, BINLOG_ID17048,
"SslCheck fail", ALERT_INSUFFICIENT_SECURITY);
}
#endif
#ifdef HITLS_TLS_CONFIG_VERSION
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLCP_DTLCP11) {
if (IS_SUPPORT_STREAM(ctx->config.tlsConfig.version)) {
ctx->config.tlsConfig.version &= ~TLS_VERSION_MASK;
ctx->config.tlsConfig.originVersionMask &= ~TLS_VERSION_MASK;
} else if (IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.version)) {
ctx->config.tlsConfig.version &= ~DTLS_VERSION_MASK;
ctx->config.tlsConfig.originVersionMask &= ~DTLS_VERSION_MASK;
}
ChangeMinMaxVersion(ctx->config.tlsConfig.version, ctx->config.tlsConfig.originVersionMask,
&ctx->config.tlsConfig.minVersion, &ctx->config.tlsConfig.maxVersion);
} else {
ctx->config.tlsConfig.version &= ~TLCP_VERSION_BITS;
ctx->config.tlsConfig.originVersionMask &= ~TLCP_VERSION_BITS;
}
#endif
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_ALPN
static int32_t ServerSelectAlpnProtocol(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
uint8_t *alpnSelected = NULL;
uint8_t alpnSelectedLen = 0u;
*/
if (ctx->globalConfig != NULL && ctx->globalConfig->alpnSelectCb != NULL) {
int32_t alpnCbRet = ctx->globalConfig->alpnSelectCb(ctx, &alpnSelected, &alpnSelectedLen,
clientHello->extension.content.alpnList, clientHello->extension.content.alpnListSize,
ctx->globalConfig->alpnUserData);
if (alpnCbRet == HITLS_ALPN_ERR_OK) {
uint8_t *alpnSelectedTmp = (uint8_t *)BSL_SAL_Calloc(alpnSelectedLen + 1, sizeof(uint8_t));
if (alpnSelectedTmp == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15227, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server malloc alpn buffer failed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MEMALLOC_FAIL;
}
memcpy(alpnSelectedTmp, alpnSelected, alpnSelectedLen);
BSL_SAL_FREE(ctx->negotiatedInfo.alpnSelected);
ctx->negotiatedInfo.alpnSelected = alpnSelectedTmp;
ctx->negotiatedInfo.alpnSelectedSize = alpnSelectedLen;
BSL_LOG_BINLOG_VARLEN(BINLOG_ID15228, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"select ALPN protocol: %s.", ctx->negotiatedInfo.alpnSelected);
* sends a fatal alert to the peer end.
* If the returned value is not HITLS_ALPN_ERR_NOACK, the system sends a fatal alert message to the peer
*/
} else if (alpnCbRet != HITLS_ALPN_ERR_NOACK) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ALPN_PROTOCOL_NO_MATCH);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15229, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server invoke alpn select cb error.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_NO_APPLICATION_PROTOCOL);
return HITLS_MSG_HANDLE_ALPN_PROTOCOL_NO_MATCH;
}
}
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_SNI
static int32_t ServerDealServerName(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret = 0;
int alert = ALERT_UNRECOGNIZED_NAME;
uint32_t serverNameSize = clientHello->extension.content.serverNameSize;
BSL_SAL_FREE(ctx->negotiatedInfo.serverName);
ctx->negotiatedInfo.serverNameSize = 0;
if (clientHello->extension.flag.haveServerName == false) {
return HITLS_SUCCESS;
}
ctx->negotiatedInfo.serverName = (uint8_t *)BSL_SAL_Dump(clientHello->extension.content.serverName,
serverNameSize * sizeof(uint8_t));
if (ctx->negotiatedInfo.serverName == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15230, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server_name malloc fail when parse extensions msg.", 0, 0, 0, 0);
return HITLS_MEMCPY_FAIL;
}
ctx->negotiatedInfo.serverNameSize = serverNameSize;
if (ctx->globalConfig == NULL || ctx->globalConfig->sniDealCb == NULL) {
ctx->negotiatedInfo.isSniStateOK = false;
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15231, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"server did not set sni callback, but continue handshake", 0, 0, 0, 0);
return HITLS_SUCCESS;
}
ret = ctx->globalConfig->sniDealCb(ctx, &alert, ctx->globalConfig->sniArg);
switch (ret) {
case HITLS_ACCEPT_SNI_ERR_OK:
ctx->negotiatedInfo.isSniStateOK = true;
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15232, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"server accept server_name from client hello msg ", 0, 0, 0, 0);
break;
case HITLS_ACCEPT_SNI_ERR_NOACK:
ctx->negotiatedInfo.isSniStateOK = false;
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15233, BSL_LOG_LEVEL_WARN, BSL_LOG_BINLOG_TYPE_RUN,
"server did not accept server_name from client hello msg, but continue handshake", 0, 0, 0, 0);
break;
default:
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15234, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server did not accept server_name from client hello msg, stop handshake",
0, 0, 0, 0);
ctx->negotiatedInfo.isSniStateOK = false;
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, (ALERT_Description)alert);
return HITLS_MSG_HANDLE_SNI_UNRECOGNIZED_NAME;
}
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_RECORD_SIZE_LIMIT
static int32_t ServerDealRecordSizeLimit(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
ctx->negotiatedInfo.recordSizeLimit = 0;
ctx->negotiatedInfo.peerRecordSizeLimit = 0;
if (clientHello->extension.flag.haveRecordSizeLimit && ctx->config.tlsConfig.recordSizeLimit != 0) {
uint16_t upperBound = (GET_VERSION_FROM_CTX(ctx) == HITLS_VERSION_TLS13 ? REC_MAX_PLAIN_LENGTH + 1
: REC_MAX_PLAIN_LENGTH);
if (clientHello->extension.content.recordSizeLimit < 64u) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_INVALID_RECORD_SIZE_LIMIT);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16245, 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 = (clientHello->extension.content.recordSizeLimit <= upperBound) ?
clientHello->extension.content.recordSizeLimit : upperBound;
}
return REC_RecOutBufReSet(ctx);
}
#endif
#ifdef HITLS_TLS_FEATURE_ETM
static int32_t ServerCheckEncryptThenMac(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
bool haveEncryptThenMac = clientHello->extension.flag.haveEncryptThenMac;
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
if (ctx->negotiatedInfo.isRenegotiation && ctx->negotiatedInfo.isEncryptThenMac && !haveEncryptThenMac) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ENCRYPT_THEN_MAC_ERR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15919, 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);
return HITLS_MSG_HANDLE_ENCRYPT_THEN_MAC_ERR;
}
#endif
if (!ctx->config.tlsConfig.isEncryptThenMac) {
return HITLS_SUCCESS;
}
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
return HITLS_SUCCESS;
}
if (haveEncryptThenMac && ctx->negotiatedInfo.cipherSuiteInfo.cipherType == HITLS_CBC_CIPHER) {
ctx->negotiatedInfo.isEncryptThenMac = true;
} else {
ctx->negotiatedInfo.isEncryptThenMac = false;
}
return HITLS_SUCCESS;
}
#endif
static int32_t ProcessClientHelloExt(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, bool isNeedSendHrr)
{
(void)ctx;
(void)clientHello;
(void)isNeedSendHrr;
int32_t ret = HITLS_SUCCESS;
ret = HS_CheckReceivedExtension(
ctx, CLIENT_HELLO, clientHello->extensionTypeMask, HS_EX_TYPE_TLS_ALLOWED_OF_CLIENT_HELLO);
if (ret != HITLS_SUCCESS) {
return ret;
}
#ifdef HITLS_TLS_FEATURE_ALPN
if (clientHello->extension.flag.haveAlpn && !isNeedSendHrr && ctx->state == CM_STATE_HANDSHAKING) {
ret = ServerSelectAlpnProtocol(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17049, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ServerSelectAlpnProtocol fail", 0, 0, 0, 0);
return ret;
}
}
#endif
#ifdef HITLS_TLS_FEATURE_RECORD_SIZE_LIMIT
if (!isNeedSendHrr) {
ret = ServerDealRecordSizeLimit(ctx, clientHello);
}
#endif
return ret;
}
#ifdef HITLS_TLS_FEATURE_SESSION
bool ServerCmpSessionIdCtx(TLS_Ctx *ctx, HITLS_Session *sess)
{
#ifdef HITLS_TLS_FEATURE_SESSION_ID
uint8_t sessionIdCtx[HITLS_SESSION_ID_CTX_MAX_SIZE];
uint32_t sessionIdCtxSize = HITLS_SESSION_ID_CTX_MAX_SIZE;
if (HITLS_SESS_GetSessionIdCtx(sess, sessionIdCtx, &sessionIdCtxSize) != HITLS_SUCCESS) {
return false;
}
if (sessionIdCtxSize != ctx->config.tlsConfig.sessionIdCtxSize) {
return false;
}
if (sessionIdCtxSize != 0 && memcmp(sessionIdCtx, ctx->config.tlsConfig.sessionIdCtx, sessionIdCtxSize) != 0) {
return false;
}
#endif
(void)ctx;
(void)sess;
return true;
}
#endif
#if defined(HITLS_TLS_PROTO_TLS_BASIC) || defined(HITLS_TLS_PROTO_DTLS12)
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
static void CheckRenegotiate(TLS_Ctx *ctx)
{
* renegotiation state only after receiving a Hello message from the client. A non-zero version number
* indicates that a handshake has been performed, in which case, the client hello process enters the
* renegotiation state again. */
if (ctx->negotiatedInfo.version != 0u) {
ctx->negotiatedInfo.isRenegotiation = true;
}
}
#endif
#ifdef HITLS_TLS_FEATURE_SESSION
#ifdef HITLS_TLS_FEATURE_ALPN
static int32_t DealResumeAlpnEx(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (clientHello->extension.flag.haveAlpn && ctx->state == CM_STATE_HANDSHAKING) {
return ServerSelectAlpnProtocol(ctx, clientHello);
}
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_FEATURE_SNI
static int32_t DealResumeServerName(TLS_Ctx *ctx, const ClientHelloMsg *clientHello,
uint32_t serverNameSize, uint8_t *serverName)
{
if (ctx->negotiatedInfo.version >= HITLS_VERSION_TLS13 && ctx->negotiatedInfo.version != HITLS_VERSION_DTLS12) {
return HITLS_SUCCESS;
}
if (ctx->globalConfig != NULL && ctx->globalConfig->sniDealCb == NULL && serverNameSize == 0) {
ctx->negotiatedInfo.isSniStateOK = false;
return HITLS_SUCCESS;
}
if (serverName != NULL && serverNameSize != 0 && clientHello->extension.flag.haveServerName == false) {
BSL_LOG_BINLOG_VARLEN(BINLOG_ID16119, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"during session resumption, session server name is [%s]", (char *)serverName);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16120, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"There is no server name in client hello msg.", 0, 0, 0, 0);
ctx->negotiatedInfo.isSniStateOK = false;
return HITLS_MSG_HANDLE_SNI_UNRECOGNIZED_NAME;
}
* resumption */
if (clientHello->extension.content.serverNameSize != serverNameSize ||
SNI_StrcaseCmp((char *)clientHello->extension.content.serverName, (char *)serverName) != 0) {
BSL_LOG_BINLOG_VARLEN(BINLOG_ID15235,
BSL_LOG_LEVEL_ERR,
BSL_LOG_BINLOG_TYPE_RUN,
"during session resume ,session servername is [%s]",
(char *)serverName);
BSL_LOG_BINLOG_VARLEN(BINLOG_ID15254, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server did not accept server_name [%s] from client hello msg",
(char *)clientHello->extension.content.serverName);
ctx->negotiatedInfo.isSniStateOK = false;
return HITLS_MSG_HANDLE_SNI_UNRECOGNIZED_NAME;
}
if (ctx->globalConfig != NULL && ctx->globalConfig->sniDealCb != NULL && serverNameSize != 0) {
int alert = ALERT_UNRECOGNIZED_NAME;
int32_t ret = ctx->globalConfig->sniDealCb(ctx, &alert, ctx->globalConfig->sniArg);
ctx->negotiatedInfo.isSniStateOK = false;
switch (ret) {
case HITLS_ACCEPT_SNI_ERR_OK:
break;
case HITLS_ACCEPT_SNI_ERR_NOACK:
return HITLS_MSG_HANDLE_SNI_UNRECOGNIZED_NAME;
default:
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, (ALERT_Description)alert);
return HITLS_MSG_HANDLE_SNI_UNRECOGNIZED_NAME;
}
}
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15236, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"during session resume, server accept server_name [%s] from client hello msg.", (char *)serverName, 0, 0, 0);
return HITLS_SUCCESS;
}
static int32_t ServerCheckResumeSni(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, HITLS_Session **sess)
{
if (*sess == NULL) {
return HITLS_SUCCESS;
}
int32_t ret = HITLS_SUCCESS;
uint8_t *serverName = NULL;
uint32_t serverNameSize = 0;
SESS_GetHostName(*sess, &serverNameSize, &serverName);
ret = DealResumeServerName(ctx, clientHello, serverNameSize, serverName);
if (ret != HITLS_SUCCESS) {
HITLS_SESS_Free(*sess);
*sess = NULL;
}
return HITLS_SUCCESS;
}
#endif
int32_t ServerCheckResumeCipherSuite(const ClientHelloMsg *clientHello, uint16_t cipherSuite)
{
for (uint16_t i = 0u; i < clientHello->cipherSuitesSize; i++) {
if (cipherSuite == clientHello->cipherSuites[i]) {
return HITLS_SUCCESS;
}
}
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15237, BSL_LOG_LEVEL_DEBUG, BSL_LOG_BINLOG_TYPE_RUN,
"Client's cipher suites do not match resume cipher suite.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_ILLEGAL_CIPHER_SUITE;
}
static int32_t ServerCheckResumeParam(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret = HITLS_SUCCESS;
uint16_t version = 0;
uint16_t cipherSuite = 0;
HITLS_Session *sess = ctx->session;
HITLS_SESS_GetProtocolVersion(sess, &version);
HITLS_SESS_GetCipherSuite(sess, &cipherSuite);
if (ServerCmpSessionIdCtx(ctx, sess) != true) {
HITLS_SESS_Free(ctx->session);
ctx->session = NULL;
ctx->negotiatedInfo.isResume = false;
return HITLS_SUCCESS;
}
if (ctx->negotiatedInfo.version != version) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15887, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"Resuming Sessions: version is inconsistent.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
return HITLS_MSG_HANDLE_ILLEGAL_VERSION;
}
ret = ServerCheckResumeCipherSuite(clientHello, cipherSuite);
if (ret != HITLS_SUCCESS) {
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return ret;
}
ret = CFG_GetCipherSuiteInfo(cipherSuite, &ctx->negotiatedInfo.cipherSuiteInfo);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17050, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"GetCipherSuiteInfo fail", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
#ifdef HITLS_TLS_FEATURE_ETM
ret = ServerCheckEncryptThenMac(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
#ifdef HITLS_TLS_FEATURE_ALPN
return DealResumeAlpnEx(ctx, clientHello);
#else
return HITLS_SUCCESS;
#endif
}
rfc7627 5.3
If a server receives a ClientHello for an abbreviated handshake
offering to resume a known previous session, it behaves as follows:
----------------------------------------------------------------------------------------------------------------
| original session | abbreviated handshake | Server behavior |
| :-------------: | :--------------------: | :-----------------------------------------------------------------:|
| true | true | agree resume (force, prefer) / full handshake no ems (forbid) |
| true | false | abort handshake |
| false | true | full handshake ems (force, prefer)/full handshake no ems (forbid)|
| false | false | abort handshake (force) / agree resume (prefer, forbid) |
*/
static int32_t ResumeCheckExtendedMasterScret(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, HITLS_Session **sess)
{
if (*sess == NULL) {
return HITLS_SUCCESS;
}
(void)clientHello;
bool haveExtMasterSecret = false;
HITLS_SESS_GetHaveExtMasterSecret(*sess, &haveExtMasterSecret);
if (haveExtMasterSecret) {
if (!clientHello->extension.flag.haveExtendedMasterSecret) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17051, 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->config.tlsConfig.emsMode != HITLS_EMS_MODE_FORBID;
if (ctx->config.tlsConfig.emsMode == HITLS_EMS_MODE_FORBID) {
HITLS_SESS_Free(*sess);
*sess = NULL;
}
} else {
if (clientHello->extension.flag.haveExtendedMasterSecret) {
HITLS_SESS_Free(*sess);
*sess = NULL;
} else if (ctx->config.tlsConfig.emsMode == HITLS_EMS_MODE_FORCE) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17052, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ExtendedMasterSecret err: EMS required but not received", 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->config.tlsConfig.emsMode != HITLS_EMS_MODE_FORBID ?
clientHello->extension.flag.haveExtendedMasterSecret :
false;
}
#ifdef HITLS_TLS_FEATURE_SNI
return ServerCheckResumeSni(ctx, clientHello, sess);
#else
return HITLS_SUCCESS;
#endif
}
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
static int32_t ServerCheckResumeTicket(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
TLS_SessionMgr *sessMgr = ctx->globalConfig->sessMgr;
HITLS_Session *sess = NULL;
uint8_t *ticketBuf = clientHello->extension.content.ticket;
uint32_t ticketBufSize = clientHello->extension.content.ticketSize;
bool isTicketExpect = false;
int32_t ret = SESSMGR_DecryptSessionTicket(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
sessMgr, &sess, ticketBuf, ticketBufSize, &isTicketExpect);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16045, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SESSMGR_DecryptSessionTicket return fail when process client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
ctx->negotiatedInfo.isTicket = isTicketExpect;
ret = ResumeCheckExtendedMasterScret(ctx, clientHello, &sess);
if (ret != HITLS_SUCCESS) {
HITLS_SESS_Free(sess);
sess = NULL;
return ret;
}
if (sess != NULL) {
if (SESS_CheckValidity(sess, (uint64_t)BSL_SAL_CurrentSysTimeGet()) == false) {
* is established */
ctx->negotiatedInfo.isTicket = true;
HITLS_SESS_Free(sess);
return HITLS_SUCCESS;
}
HITLS_SESS_Free(ctx->session);
ctx->session = sess;
ctx->negotiatedInfo.isResume = true;
* filled in the serverHello and returned */
HITLS_SESS_SetSessionId(ctx->session, clientHello->sessionId, clientHello->sessionIdSize);
}
return HITLS_SUCCESS;
}
#endif
static int32_t ServerCheckResume(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
ctx->negotiatedInfo.isResume = false;
ctx->negotiatedInfo.isTicket = false;
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
if (ctx->negotiatedInfo.isRenegotiation && !ctx->config.tlsConfig.isResumptionOnRenego) {
return HITLS_SUCCESS;
}
#endif
HITLS_Session *sess = NULL;
uint32_t ticketBufSize = clientHello->extension.content.ticketSize;
bool supportTicket = IsTicketSupport(ctx);
MUST NOT attempt to use the Session ID in the ClientHello for stateful
session resumption. */
if (ticketBufSize == 0u) {
if (supportTicket && clientHello->extension.flag.haveTicket) {
ctx->negotiatedInfo.isTicket = true;
}
sess = SESSMGR_Find(ctx, clientHello->sessionId, clientHello->sessionIdSize);
int32_t ret = ResumeCheckExtendedMasterScret(ctx, clientHello, &sess);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17053, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ResumeCheckExtendedMasterScret fail", 0, 0, 0, 0);
HITLS_SESS_Free(sess);
sess = NULL;
return ret;
}
if (sess != NULL) {
HITLS_SESS_Free(ctx->session);
ctx->session = sess;
sess = NULL;
ctx->negotiatedInfo.isResume = true;
}
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
if (supportTicket) {
return ServerCheckResumeTicket(ctx, clientHello);
}
#endif
return HITLS_SUCCESS;
}
#endif
static int32_t ServerCheckRenegoInfoDuringFirstHandshake(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (!clientHello->haveEmptyRenegoScsvCipher && !clientHello->extension.flag.haveSecRenego) {
return HITLS_SUCCESS;
}
if (clientHello->extension.content.secRenegoInfoSize != 0) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15889, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"secRenegoInfoSize should be 0 in server initial handhsake.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
ctx->negotiatedInfo.isSecureRenegotiation = true;
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
static int32_t ServerCheckRenegoInfoDuringRenegotiation(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (clientHello->haveEmptyRenegoScsvCipher) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15890, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SCSV cipher should not be in server secure renegotiation.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
if (clientHello->extension.content.secRenegoInfoSize != ctx->negotiatedInfo.clientVerifyDataSize) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15891, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"secRenegoInfoSize verify failed during server renegotiation.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
if (memcmp(clientHello->extension.content.secRenegoInfo, ctx->negotiatedInfo.clientVerifyData,
ctx->negotiatedInfo.clientVerifyDataSize) != 0) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RENEGOTIATION_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15892, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"secRenegoInfo verify failed during server renegotiation.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_RENEGOTIATION_FAIL;
}
return HITLS_SUCCESS;
}
#endif
static int32_t ServerCheckAndProcessRenegoInfo(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (!ctx->negotiatedInfo.isRenegotiation) {
return ServerCheckRenegoInfoDuringFirstHandshake(ctx, clientHello);
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
return ServerCheckRenegoInfoDuringRenegotiation(ctx, clientHello);
#else
return HITLS_SUCCESS;
#endif
}
static int32_t ServerSelectCipherSuiteInfo(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret = ServerSelectCipherSuite(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15239, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server select cipher suite fail.", 0, 0, 0, 0);
return ret;
}
#ifdef HITLS_TLS_FEATURE_ETM
ret = ServerCheckEncryptThenMac(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
return HITLS_SUCCESS;
}
static int32_t ServerProcessClientHelloExt(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
#ifdef HITLS_TLS_FEATURE_EXTENDED_MASTER_SECRET
int32_t ret = HITLS_SUCCESS;
(void)ret;
(void)clientHello;
(void)ctx;
if (ctx->config.tlsConfig.emsMode == HITLS_EMS_MODE_FORCE &&
!clientHello->extension.flag.haveExtendedMasterSecret) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16196, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"The peer does not support the extended master key.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_INVALID_EXTENDED_MASTER_SECRET;
}
if (ctx->config.tlsConfig.emsMode != HITLS_EMS_MODE_FORBID) {
ctx->negotiatedInfo.isExtendedMasterSecret = clientHello->extension.flag.haveExtendedMasterSecret;
} else {
ctx->negotiatedInfo.isExtendedMasterSecret = false;
}
#endif
return ProcessClientHelloExt(ctx, clientHello, false);
}
static int32_t ServerCheckVersionDowngrade(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (!clientHello->haveFallBackScsvCipher) {
return HITLS_SUCCESS;
}
if (IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask) &&
!IS_SUPPORT_TLCP(ctx->config.tlsConfig.originVersionMask)) {
if (ctx->negotiatedInfo.version > ctx->config.tlsConfig.maxVersion) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15339, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"dtls server supports a higher protocol version.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INAPPROPRIATE_FALLBACK);
return HITLS_MSG_HANDLE_ERR_INAPPROPRIATE_FALLBACK;
}
return HITLS_SUCCESS;
}
if (ctx->negotiatedInfo.version < ctx->config.tlsConfig.maxVersion) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15335, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server supports a higher protocol version.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INAPPROPRIATE_FALLBACK);
return HITLS_MSG_HANDLE_ERR_INAPPROPRIATE_FALLBACK;
}
return HITLS_SUCCESS;
}
static int32_t ServerCheckAndProcessClientHello(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
HS_Ctx *hsCtx = (HS_Ctx *)ctx->hsCtx;
int32_t ret = ServerSelectNegoVersion(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15238, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server select negotiated version fail.", 0, 0, 0, 0);
return ret;
}
ret = ServerCheckVersionDowngrade(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
memcpy(hsCtx->clientRandom, clientHello->randomValue, HS_RANDOM_SIZE);
ret = ServerCheckAndProcessRenegoInfo(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
#ifdef HITLS_TLS_FEATURE_SESSION
ret = ServerCheckResume(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (ctx->negotiatedInfo.isResume) {
return ServerCheckResumeParam(ctx, clientHello);
}
#endif
#ifdef HITLS_TLS_FEATURE_SNI
ret = ServerDealServerName(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
return ret;
}
#ifdef HITLS_TLS_FEATURE_CERT_CB
int32_t ProcessCertCallback(TLS_Ctx *ctx)
{
CERT_MgrCtx *mgrCtx = ctx->config.tlsConfig.certMgrCtx;
if (mgrCtx == NULL) {
return HITLS_SUCCESS;
}
HITLS_CertCb certCb = mgrCtx->certCb;
void *certCbArg = mgrCtx->certCbArg;
if (certCb != NULL) {
int32_t ret = certCb(ctx, certCbArg);
if (ret == HITLS_CERT_CALLBACK_RETRY) {
BSL_ERR_PUSH_ERROR(HITLS_CALLBACK_CERT_RETRY);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15243, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"certCb suspend when process client hello.", 0, 0, 0, 0);
ctx->rwstate = HITLS_X509_LOOKUP;
return HITLS_CALLBACK_CERT_RETRY;
} else if (ret != HITLS_CERT_CALLBACK_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_CALLBACK_CERT_ERROR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15243, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"certCb fail when process client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_CALLBACK_CERT_ERROR;
}
}
return HITLS_SUCCESS;
}
#endif
static int32_t ServerPostProcessClientHello(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_CERT_CB
ret = ProcessCertCallback(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
ret = ServerSelectCipherSuiteInfo(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
return ServerProcessClientHelloExt(ctx, clientHello);
}
#endif
#ifdef HITLS_TLS_FEATURE_CLIENT_HELLO_CB
static int32_t ClientHelloCbCheck(TLS_Ctx *ctx)
{
int32_t ret;
int32_t alert = ALERT_INTERNAL_ERROR;
const TLS_Config *tlsConfig = ctx->globalConfig;
if (tlsConfig != NULL && tlsConfig->clientHelloCb != NULL) {
ret = tlsConfig->clientHelloCb(ctx, &alert, tlsConfig->clientHelloCbArg);
if (ret == HITLS_CLIENT_HELLO_RETRY) {
BSL_ERR_PUSH_ERROR(HITLS_CALLBACK_CLIENT_HELLO_RETRY);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15239, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ClientHello callback error.", 0, 0, 0, 0);
ctx->rwstate = HITLS_CLIENT_HELLO_CB;
return HITLS_CALLBACK_CLIENT_HELLO_RETRY;
} else if (ret != HITLS_CLIENT_HELLO_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_CALLBACK_CLIENT_HELLO_ERROR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15240, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"The result of ClientHello callback is %d, and the reason is %d.", ret, alert, 0, 0);
if (alert >= ALERT_CLOSE_NOTIFY && alert <= ALERT_UNKNOWN) {
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, alert);
}
return HITLS_CALLBACK_CLIENT_HELLO_ERROR;
}
}
return HITLS_SUCCESS;
}
#endif
#if defined(HITLS_TLS_PROTO_DTLS12) && defined(HITLS_BSL_UIO_UDP)
static int32_t PrepareDtlsCookie(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret;
uint8_t cookie[TLS_HS_MAX_COOKIE_SIZE] = {0};
uint32_t cookieSize = TLS_HS_MAX_COOKIE_SIZE;
ret = HS_CalcCookie(ctx, clientHello, cookie, &cookieSize, false);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15241, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"calc cookie fail when process client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
BSL_SAL_FREE(ctx->negotiatedInfo.cookie);
ctx->negotiatedInfo.cookie = (uint8_t *)BSL_SAL_Dump(cookie, cookieSize);
if (ctx->negotiatedInfo.cookie == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15242, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"malloc cookie fail when process client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MEMALLOC_FAIL;
}
ctx->negotiatedInfo.cookieSize = (uint32_t)cookieSize;
return HITLS_SUCCESS;
}
static int32_t DtlsServerCheckAndProcessCookie(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, bool *isCookieValid)
{
int32_t ret = HS_CheckCookie(ctx, clientHello, isCookieValid);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15243, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"HS_CheckCookie fail when process client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
if (!*isCookieValid) {
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
If the cookie is empty, the hello verify request is sent */
if ((clientHello->cookieLen != 0u) && (ctx->negotiatedInfo.isRenegotiation)) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_VERIFY_COOKIE_ERR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15911, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"client hello cookie verify fail during renegotiation.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_VERIFY_COOKIE_ERR;
}
#endif
ret = PrepareDtlsCookie(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
return HITLS_SUCCESS;
}
#endif
#if defined(HITLS_TLS_PROTO_TLS_BASIC) || defined(HITLS_TLS_PROTO_DTLS12)
int32_t ServerRecvClientHelloProcess(TLS_Ctx *ctx, const HS_Msg *msg, bool isNeedClientHelloCb)
{
(void)isNeedClientHelloCb;
int32_t ret;
const ClientHelloMsg *clientHello = &msg->body.clientHello;
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
CheckRenegotiate(ctx);
#endif
if (ctx->hsCtx->readSubState == TLS_PROCESS_STATE_A) {
#ifdef HITLS_TLS_FEATURE_CLIENT_HELLO_CB
if (isNeedClientHelloCb) {
ret = ClientHelloCbCheck(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#endif
#if defined(HITLS_TLS_PROTO_DTLS12) && defined(HITLS_BSL_UIO_UDP)
if (IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask) &&
!BSL_UIO_GetUioChainTransportType(ctx->uio, BSL_UIO_SCTP)) {
bool isCookieValid = false;
ret = DtlsServerCheckAndProcessCookie(ctx, clientHello, &isCookieValid);
if (ret == HITLS_SUCCESS && !isCookieValid) {
return HS_ChangeState(ctx, TRY_SEND_HELLO_VERIFY_REQUEST);
} else if (ret != HITLS_SUCCESS) {
return ret;
}
}
#endif
ret = ServerCheckAndProcessClientHello(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return RETURN_ERROR_NUMBER_PROCESS(ret, BINLOG_ID15244, "server process clientHello fail");
}
if (!ctx->negotiatedInfo.isResume) {
ctx->hsCtx->readSubState = TLS_PROCESS_STATE_B;
}
}
if (ctx->hsCtx->readSubState == TLS_PROCESS_STATE_B) {
ret = ServerPostProcessClientHello(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return RETURN_ERROR_NUMBER_PROCESS(ret, BINLOG_ID17056, "PostProcessClientHello fail");
}
}
#ifdef HITLS_TLS_FEATURE_RENEGOTIATION
if (ctx->state == CM_STATE_RENEGOTIATION && !ctx->userRenego) {
ctx->negotiatedInfo.isRenegotiation = true;
ctx->negotiatedInfo.renegotiationNum++;
}
#endif
return HS_ChangeState(ctx, TRY_SEND_SERVER_HELLO);
}
#endif
#ifdef HITLS_TLS_PROTO_TLS13
static uint32_t GetClientKeMode(const ExtensionContent *extension)
{
uint32_t clientKeMode = 0;
for (uint32_t i = 0; i < extension->keModesSize; i++) {
if (extension->keModes[i] == PSK_KE) {
clientKeMode |= TLS13_KE_MODE_PSK_ONLY;
} else if (extension->keModes[i] == PSK_DHE_KE) {
clientKeMode |= TLS13_KE_MODE_PSK_WITH_DHE;
}
}
return clientKeMode;
}
static bool CheckClientHelloKeyShareValid(const ClientHelloMsg *clientHello, uint16_t keyShareGroup)
{
for (uint32_t i = 0; i < clientHello->extension.content.supportedGroupsSize; i++) {
if (keyShareGroup == clientHello->extension.content.supportedGroups[i]) {
return true;
}
}
return false;
}
static int32_t ServerCheckKeyShare(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
* reported if the keyshare does not exist */
if (clientHello->extension.flag.haveKeyShare == false || clientHello->extension.content.supportedGroupsSize == 0u ||
ProcessEcdheCipherSuite(ctx, clientHello) != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_HANDSHAKE_FAILURE);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16137, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"unable to negotiate a supported set of parameters.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_HANDSHAKE_FAILURE;
}
KeyShareParam *keyShare = &ctx->hsCtx->kxCtx->keyExchParam.share;
uint16_t selectGroup = keyShare->groups[0];
KeyShare *cache = clientHello->extension.content.keyShare;
replace the original "key_share" extension with one containing only a
new KeyShareEntry for the group indicated in the selected_group field
of the triggering HelloRetryRequest. */
if (ctx->hsCtx->haveHrr) {
if (cache == NULL || cache->head.next != cache->head.prev ||
BSL_LIST_ENTRY(cache->head.next, KeyShare, head)->group != selectGroup) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16164, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"hrr client hello key Share error.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP;
}
}
return HITLS_SUCCESS;
}
static int32_t Tls13ServerProcessKeyShare(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, bool *isNeedSendHrr)
{
* reported if the keyshare does not exist */
int32_t ret = ServerCheckKeyShare(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
KeyShareParam *keyShare = &ctx->hsCtx->kxCtx->keyExchParam.share;
uint16_t selectGroup = keyShare->groups[0];
ListHead *node = NULL;
ListHead *tmpNode = NULL;
KeyShare *cur = NULL;
KeyShare *cache = clientHello->extension.content.keyShare;
if (cache == NULL) {
*isNeedSendHrr = true;
return HITLS_SUCCESS;
}
LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(cache->head)) {
cur = BSL_LIST_ENTRY(node, KeyShare, head);
for groups not listed in the client's "supported_groups" extension.
Servers MAY check for violations of these rules and abort the
handshake with an "illegal_parameter" alert if one is violated. */
if (!CheckClientHelloKeyShareValid(clientHello, cur->group)) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID16138,
"The group in the keyshare does not exist in the support group extension.", ALERT_ILLEGAL_PARAMETER);
}
}
LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(cache->head)) {
cur = BSL_LIST_ENTRY(node, KeyShare, head);
if (cur->group != selectGroup) {
continue;
}
*isNeedSendHrr = false;
ctx->hsCtx->kxCtx->pubKeyLen = cur->keyExchangeSize;
if (HS_GetCryptLength(ctx, HITLS_CRYPT_INFO_CMD_GET_PUBLIC_KEY_LEN, keyShare->groups[0]) !=
ctx->hsCtx->kxCtx->pubKeyLen) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP);
return RETURN_ALERT_PROCESS(ctx, HITLS_MSG_HANDLE_ILLEGAL_SELECTED_GROUP, BINLOG_ID16189,
"invalid keyShare length.", ALERT_ILLEGAL_PARAMETER);
}
BSL_SAL_FREE(ctx->hsCtx->kxCtx->peerPubkey);
ctx->hsCtx->kxCtx->peerPubkey = BSL_SAL_Dump(cur->keyExchange, cur->keyExchangeSize);
if (ctx->hsCtx->kxCtx->peerPubkey == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15245, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"malloc peerPubkey fail when process client key share.", 0, 0, 0, 0);
return HITLS_MEMALLOC_FAIL;
}
ctx->negotiatedInfo.negotiatedGroup = selectGroup;
return HITLS_SUCCESS;
}
*/
*isNeedSendHrr = true;
return HITLS_SUCCESS;
}
#if defined(HITLS_TLS_FEATURE_SESSION) || defined(HITLS_TLS_FEATURE_PSK)
static int32_t GetPskFromSession(TLS_Ctx *ctx, HITLS_Session *pskSession, uint8_t *psk, uint32_t pskLen,
uint32_t *usedLen)
{
uint32_t tmpLen = pskLen;
int32_t ret = HITLS_SESS_GetMasterKey(pskSession, psk, &tmpLen);
if (ret != HITLS_SUCCESS) {
*/
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
*usedLen = tmpLen;
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_FEATURE_PSK
static int32_t PskFindSession(TLS_Ctx *ctx, const uint8_t *id, uint32_t idLen, HITLS_Session **pskSession)
{
if (ctx->config.tlsConfig.pskFindSessionCb == NULL) {
return HITLS_SUCCESS;
}
int32_t ret = ctx->config.tlsConfig.pskFindSessionCb(ctx, id, idLen, pskSession);
if (ret != HITLS_PSK_FIND_SESSION_CB_SUCCESS) {
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MSG_HANDLE_PSK_FIND_SESSION_FAIL;
}
return HITLS_SUCCESS;
}
static int32_t GetPskByIdentity(TLS_Ctx *ctx, const uint8_t *id, uint32_t idLen, uint8_t *psk, uint32_t *pskLen)
{
if (ctx->config.tlsConfig.pskServerCb == NULL) {
*pskLen = 0;
return HITLS_SUCCESS;
}
uint8_t *strId = BSL_SAL_Calloc(1u, idLen + 1);
if (strId == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17056, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "Calloc fail", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MEMALLOC_FAIL;
}
memcpy(strId, id, idLen);
strId[idLen] = '\0';
uint32_t usedLen = ctx->config.tlsConfig.pskServerCb(ctx, strId, psk, *pskLen);
BSL_SAL_FREE(strId);
if (usedLen > HS_PSK_MAX_LEN) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17057, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "usedLen err", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MSG_HANDLE_ILLEGAL_PSK_LEN;
}
*pskLen = usedLen;
return HITLS_SUCCESS;
}
#endif
static int32_t Tls13ServerSetPskInfo(TLS_Ctx *ctx, uint8_t *psk, uint32_t pskLen, uint16_t index)
{
PskInfo13 *pskInfo13 = &ctx->hsCtx->kxCtx->pskInfo13;
BSL_SAL_ClearFree(pskInfo13->psk, pskInfo13->pskLen);
pskInfo13->psk = BSL_SAL_Dump(psk, pskLen);
if (pskInfo13->psk == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17058, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "Dump fail", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MEMALLOC_FAIL;
}
pskInfo13->pskLen = pskLen;
pskInfo13->selectIndex = index;
return HITLS_SUCCESS;
}
static bool IsPSKValid(TLS_Ctx *ctx, HITLS_Session *pskSession)
{
uint16_t version, cipherSuite;
HITLS_SESS_GetProtocolVersion(pskSession, &version);
if (version != HITLS_VERSION_TLS13) {
return false;
}
HITLS_SESS_GetCipherSuite(pskSession, &cipherSuite);
CipherSuiteInfo cipherInfo = {0};
int32_t ret = CFG_GetCipherSuiteInfo(cipherSuite, &cipherInfo);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17059, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"GetCipherSuiteInfo fail", 0, 0, 0, 0);
return false;
}
if (cipherInfo.hashAlg != ctx->negotiatedInfo.cipherSuiteInfo.hashAlg) {
return false;
}
return true;
}
static int32_t TLS13ServerProcessTicket(TLS_Ctx *ctx, PreSharedKey *cur,
uint8_t *psk, uint32_t *pskLen)
{
const uint8_t *ticket = cur->identity;
uint32_t ticketLen = cur->identitySize;
bool isTicketExcept = 0;
HITLS_Session *pskSession = NULL;
int32_t ret = SESSMGR_DecryptSessionTicket(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
ctx->globalConfig->sessMgr, &pskSession, ticket, ticketLen, &isTicketExcept);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16048, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"Decrypt Ticket fail when processing client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
if (pskSession == NULL) {
*pskLen = 0;
return HITLS_SUCCESS;
}
if (!IsPSKValid(ctx, pskSession) ||
!SESS_CheckValidity(pskSession, (uint64_t)BSL_SAL_CurrentSysTimeGet())) {
*pskLen = 0;
HITLS_SESS_Free(pskSession);
return HITLS_SUCCESS;
}
if (ServerCmpSessionIdCtx(ctx, pskSession) != true) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16075, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"TLS1.3 Resuming Session: session id ctx is inconsistent.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
HITLS_SESS_Free(pskSession);
return HITLS_MSG_HANDLE_SESSION_ID_CTX_ILLEGAL;
}
ret = GetPskFromSession(ctx, pskSession, psk, *pskLen, pskLen);
if (ret != HITLS_SUCCESS) {
HITLS_SESS_Free(pskSession);
return ret;
}
if (*pskLen == 0) {
HITLS_SESS_Free(pskSession);
return HITLS_SUCCESS;
}
HITLS_SESS_Free(ctx->session);
ctx->session = pskSession;
ctx->negotiatedInfo.isResume = true;
return HITLS_SUCCESS;
}
static int32_t ServerFindPsk(TLS_Ctx *ctx, PreSharedKey *cur,
uint8_t *psk, uint32_t *pskLen)
{
int32_t ret = HITLS_SUCCESS;
ctx->negotiatedInfo.isResume = false;
#ifdef HITLS_TLS_FEATURE_PSK
const uint8_t *identity = cur->identity;
uint32_t identitySize = cur->identitySize;
uint32_t pskSize = *pskLen;
HITLS_Session *pskSession = NULL;
ret = PskFindSession(ctx, identity, identitySize, &pskSession);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (pskSession != NULL) {
if (IsPSKValid(ctx, pskSession) == false) {
HITLS_SESS_Free(pskSession);
*pskLen = 0;
return HITLS_SUCCESS;
}
ret = GetPskFromSession(ctx, pskSession, psk, pskSize, pskLen);
HITLS_SESS_Free(pskSession);
return ret;
}
* By default, the hash algorithm used by the pskSession cipher suite is SHA_256.
* In this case, you only need to check whether the hash algorithm of the negotiated cipher suite is SHA_256.
*/
if (ctx->negotiatedInfo.cipherSuiteInfo.hashAlg == HITLS_HASH_SHA_256) {
ret = GetPskByIdentity(ctx, identity, identitySize, psk, &pskSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (pskSize > 0u) {
*pskLen = pskSize;
return HITLS_SUCCESS;
}
}
#endif
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
ret = TLS13ServerProcessTicket(ctx, cur, psk, pskLen);
#else
if (ret == HITLS_SUCCESS && *pskLen != 0) {
*pskLen = 0;
return HITLS_SUCCESS;
}
#endif
return ret;
}
int32_t CompareBinder(TLS_Ctx *ctx, const PreSharedKey *pskNode, uint8_t *psk, uint32_t pskLen,
uint32_t truncateHelloLen)
{
int32_t ret;
uint8_t *recvBinder = pskNode->binder;
uint32_t recvBinderLen = pskNode->binderSize;
HITLS_HashAlgo hashAlg = ctx->negotiatedInfo.cipherSuiteInfo.hashAlg;
bool isExternalPsk = !(ctx->negotiatedInfo.isResume);
uint8_t computedBinder[HS_MAX_BINDER_SIZE] = {0};
uint32_t binderLen = HS_GetBinderLen(NULL, &hashAlg);
if (binderLen == 0 || binderLen != recvBinderLen || binderLen > HS_MAX_BINDER_SIZE) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17060, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"binderLen err", 0, 0, 0, 0);
return HITLS_INTERNAL_EXCEPTION;
}
ret = VERIFY_CalcPskBinder(ctx, hashAlg, isExternalPsk, psk, pskLen, ctx->hsCtx->msgBuf, truncateHelloLen,
computedBinder, binderLen);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = ConstTimeMemcmp(computedBinder, recvBinder, binderLen) == 0 ? HITLS_INTERNAL_EXCEPTION : HITLS_SUCCESS;
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17061, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"memcmp fail, ret %d", ret, 0, 0, 0);
return HITLS_INTERNAL_EXCEPTION;
}
return ret;
}
Section 4.2.11.2 below). If this value is not present or does not validate, the server MUST abort the handshake. Servers
SHOULD NOT attempt to validate multiple binders; rather, they SHOULD select a single PSK and validate solely the binder
that corresponds to that PSK.
*/
static int32_t ServerSelectPskAndCheckBinder(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
int32_t ret = HITLS_SUCCESS;
uint16_t index = 0;
uint8_t psk[HS_PSK_MAX_LEN] = {0};
ListHead *node = NULL;
ListHead *tmpNode = NULL;
PreSharedKey *cur = NULL;
PreSharedKey *offeredPsks = clientHello->extension.content.preSharedKey;
LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(offeredPsks->pskNode))
{
uint32_t pskLen = HS_PSK_MAX_LEN;
cur = BSL_LIST_ENTRY(node, PreSharedKey, pskNode);
ret = ServerFindPsk(ctx, cur, psk, &pskLen);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (pskLen == 0) {
index++;
continue;
}
ret = Tls13ServerSetPskInfo(ctx, psk, pskLen, index);
if (ret != HITLS_SUCCESS) {
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
return ret;
}
ret = CompareBinder(ctx, cur, psk, pskLen, clientHello->truncateHelloLen);
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
if (ret != HITLS_SUCCESS) {
operation failed, including being unable to correctly verify a
signature or validate a Finished message or a PSK binder. */
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_DECRYPT_ERROR);
return ret;
}
cur->isValid = true;
break;
}
return ret;
}
#endif
static int32_t Tls13ServerSetSessionId(TLS_Ctx *ctx, const uint8_t *sessionId, uint32_t sessionIdSize)
{
if (sessionIdSize == 0) {
ctx->hsCtx->sessionIdSize = sessionIdSize;
return HITLS_SUCCESS;
}
uint8_t *tmpSession = BSL_SAL_Dump(sessionId, sessionIdSize);
if (tmpSession == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15248, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"malloc sessionId fail when process client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_MEMALLOC_FAIL;
}
BSL_SAL_FREE(ctx->hsCtx->sessionId);
ctx->hsCtx->sessionId = tmpSession;
ctx->hsCtx->sessionIdSize = sessionIdSize;
return HITLS_SUCCESS;
}
static int32_t Tls13ServerCheckClientHelloExtension(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
do {
both a "signature_algorithms" extension and a "supported_groups"
extension. */
if ((!clientHello->extension.flag.havePreShareKey) && (!clientHello->extension.flag.haveSignatureAlgorithms ||
!clientHello->extension.flag.haveSupportedGroups)) {
break;
}
a "key_share" extension, and vice versa. */
if ((clientHello->extension.flag.haveSupportedGroups && !clientHello->extension.flag.haveKeyShare) ||
(!clientHello->extension.flag.haveSupportedGroups && clientHello->extension.flag.haveKeyShare)) {
break;
}
offers a "pre_shared_key" extension. */
if (clientHello->extension.flag.havePreShareKey && !clientHello->extension.flag.havePskExMode) {
break;
}
uint32_t clientKeMode = GetClientKeMode(&clientHello->extension.content);
if (clientHello->extension.flag.havePreShareKey &&
(clientKeMode & TLS13_KE_MODE_PSK_WITH_DHE) == TLS13_KE_MODE_PSK_WITH_DHE &&
!clientHello->extension.flag.haveKeyShare) {
break;
}
return HITLS_SUCCESS;
} while (false);
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_MISSING_EXTENSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16139, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"invalid client hello: missing extension.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_MISSING_EXTENSION);
return HITLS_MSG_HANDLE_MISSING_EXTENSION;
}
static int32_t Tls13ServerCheckSecondClientHello(TLS_Ctx *ctx, ClientHelloMsg *clientHello)
{
if (ctx->hsCtx->haveHrr) {
if (ctx->hsCtx->firstClientHello->cipherSuitesSize != clientHello->cipherSuitesSize ||
memcmp(ctx->hsCtx->firstClientHello->cipherSuites, clientHello->cipherSuites,
clientHello->cipherSuitesSize * sizeof(uint16_t)) != 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17062, BSL_LOG_LEVEL_DEBUG, BSL_LOG_BINLOG_TYPE_RUN,
"Server's cipher suites do not match client's cipher suite.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_ILLEGAL_CIPHER_SUITE;
}
return HITLS_SUCCESS;
}
if (ctx->hsCtx->firstClientHello != NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17063, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"internal exception occurs", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_INTERNAL_EXCEPTION;
}
ctx->hsCtx->firstClientHello = (ClientHelloMsg *)BSL_SAL_Dump(clientHello, sizeof(ClientHelloMsg));
if (ctx->hsCtx->firstClientHello == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16147, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "clientHello malloc fail.", 0,
0, 0, 0);
return HITLS_MEMALLOC_FAIL;
}
clientHello->refCnt = 1;
return HITLS_SUCCESS;
}
static int32_t Tls13ServerCheckCompressionMethods(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (clientHello->compressionMethodsSize != 1u) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_INVALID_COMPRESSION_METHOD);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16162, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"the compression length of client hello is incorrect.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_INVALID_COMPRESSION_METHOD;
}
if (clientHello->compressionMethods[0] == 0u) {
return HITLS_SUCCESS;
}
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_INVALID_COMPRESSION_METHOD);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16163, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"can not find a appropriate compression method in client hello.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_INVALID_COMPRESSION_METHOD;
}
static int32_t Tls13ServerBasicCheckClientHello(TLS_Ctx *ctx, ClientHelloMsg *clientHello)
{
int32_t ret = Tls13ServerCheckSecondClientHello(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
ctx->negotiatedInfo.version = HITLS_VERSION_TLS13;
ret = Tls13ServerCheckCompressionMethods(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
memcpy(ctx->hsCtx->clientRandom, clientHello->randomValue, HS_RANDOM_SIZE);
ret = Tls13ServerSetSessionId(ctx, clientHello->sessionId, clientHello->sessionIdSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
return ServerSelectCipherSuite(ctx, clientHello);
}
static int32_t Tls13ServerSelectCert(TLS_Ctx *ctx, const ClientHelloMsg *clientHello)
{
if (ctx->hsCtx->kxCtx->pskInfo13.psk != NULL) {
return HITLS_SUCCESS;
}
*/
if (clientHello->extension.content.signatureAlgorithms == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17065, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"miss signatureAlgorithms extension", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_MISSING_EXTENSION);
return HITLS_MSG_HANDLE_MISSING_EXTENSION;
}
CERT_ExpectInfo expectCertInfo = {0};
expectCertInfo.certType = CERT_TYPE_UNKNOWN;
expectCertInfo.signSchemeList = clientHello->extension.content.signatureAlgorithms;
expectCertInfo.signSchemeNum = clientHello->extension.content.signatureAlgorithmsSize;
uint8_t pointFormat = HITLS_POINT_FORMAT_UNCOMPRESSED;
expectCertInfo.ecPointFormatList = &pointFormat;
expectCertInfo.ecPointFormatNum = 1u;
int32_t ret = HS_SelectCertByInfo(ctx, &expectCertInfo);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_CERT_ERR_SELECT_CERTIFICATE);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15219, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"have no suitable cert. ret %d", ret, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_ERR_NO_SERVER_CERTIFICATE;
}
return HITLS_SUCCESS;
}
static int32_t Tls13ServerCheckClientHello(TLS_Ctx *ctx, ClientHelloMsg *clientHello, bool *isNeedSendHrr)
{
uint32_t selectKeMode = 0;
int32_t ret = Tls13ServerBasicCheckClientHello(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = Tls13ServerCheckClientHelloExtension(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
uint32_t clientKeMode = GetClientKeMode(&clientHello->extension.content);
selectKeMode = clientKeMode & ctx->config.tlsConfig.keyExchMode;
#if defined(HITLS_TLS_FEATURE_SESSION) || defined(HITLS_TLS_FEATURE_PSK)
if (clientHello->extension.flag.havePreShareKey && selectKeMode != 0) {
ret = ServerSelectPskAndCheckBinder(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_PSK_INVALID);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15940, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"ServerSelectPskAndCheckBinder failed. ret %d", ret, 0, 0, 0);
return HITLS_MSG_HANDLE_PSK_INVALID;
}
}
#endif
if (ctx->hsCtx->kxCtx->pskInfo13.psk == NULL ||
(selectKeMode & TLS13_KE_MODE_PSK_WITH_DHE) == TLS13_KE_MODE_PSK_WITH_DHE) {
ret = Tls13ServerProcessKeyShare(ctx, clientHello, isNeedSendHrr);
*/
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#ifdef HITLS_TLS_FEATURE_SNI
ret = ServerDealServerName(ctx, clientHello);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
return ret;
}
static int32_t Tls13ServerPostCheckClientHello(TLS_Ctx *ctx, ClientHelloMsg *clientHello, bool *isNeedSendHrr)
{
int32_t ret;
#ifdef HITLS_TLS_FEATURE_CERT_CB
ret = ProcessCertCallback(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
ret = ProcessClientHelloExt(ctx, clientHello, (*isNeedSendHrr));
if (ret != HITLS_SUCCESS) {
return ret;
}
return Tls13ServerSelectCert(ctx, clientHello);
}
static int32_t CheckSupportVersion(TLS_Ctx *ctx, uint16_t version, uint16_t *selectVersion)
{
if (version >= HITLS_VERSION_TLS13 && !IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask)) {
version = HITLS_VERSION_TLS12;
}
uint32_t versionBits = MapVersion2VersionBit(IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask), version);
if ((versionBits & ctx->config.tlsConfig.version) == versionBits && (versionBits != 0)) {
*selectVersion = version;
return HITLS_SUCCESS;
}
BSL_LOG_BINLOG_FIXLEN(
BINLOG_ID17066, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "negotiate version fail", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
bool IsTls13KeyExchAvailable(TLS_Ctx *ctx)
{
#ifdef HITLS_TLS_FEATURE_PSK
TLS_Config *config = &ctx->config.tlsConfig;
if (config->pskServerCb != NULL) {
return true;
}
if (config->pskFindSessionCb != NULL) {
return true;
}
#endif
return Tls13HasCertificate(ctx);
}
static int32_t SelectVersion(TLS_Ctx *ctx, const ClientHelloMsg *clientHello, uint16_t *selectVersion)
{
int32_t ret;
uint16_t version = clientHello->version;
* According to rfc8446 section 4.2.1 if the ClientHello does not have the supportedVersions extension,
* Then the server must negotiate TLS 1.2 or earlier as specified in rfc5246.
*/
if (clientHello->extension.content.supportedVersionsCount == 0) {
ret = CheckSupportVersion(ctx, version, selectVersion);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16134, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server cannot negotiate a version.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
}
return ret;
}
* section 4.1.2 in RFC 8446 */
if (version != HITLS_VERSION_TLS12) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15249, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"illegal client legacy_version(0x%02x).", version, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
uint32_t versionBits;
uint16_t versions[] = {HITLS_VERSION_DTLS12, HITLS_VERSION_TLS13, HITLS_VERSION_TLS12, HITLS_VERSION_TLCP_DTLCP11};
for (uint32_t j = 0; j < sizeof(versions) / sizeof(uint16_t); j++) {
version = versions[j];
for (int i = 0; i < clientHello->extension.content.supportedVersionsCount; i++) {
versionBits = MapVersion2VersionBit(IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask), version);
if (clientHello->extension.content.supportedVersions[i] != version ||
(versionBits & ctx->config.tlsConfig.version) == 0) {
continue;
}
if (((version == HITLS_VERSION_TLS13) && (!IsTls13KeyExchAvailable(ctx)))) {
* than SSL3.0. */
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17380, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"tls1.3 handshake state error: TLS1.3 must have an available PSK or certificate", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_HANDSHAKE_FAILURE);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
* extension but does not contain 0x0304 in the version list, Therefore, if a matching version is found,
* even if the version is an earlier version, the system directly returns */
*selectVersion = version;
return HITLS_SUCCESS;
}
}
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15250, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server cannot negotiate a version.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_PROTOCOL_VERSION);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
static int32_t UpdateServerBaseKeyExMode(TLS_Ctx *ctx)
{
uint32_t tls13BasicKeyExMode = 0;
KeyExchCtx *kxCtx = ctx->hsCtx->kxCtx;
if (kxCtx->pskInfo13.psk != NULL && kxCtx->peerPubkey != NULL) {
tls13BasicKeyExMode = TLS13_KE_MODE_PSK_WITH_DHE;
} else if (kxCtx->pskInfo13.psk != NULL) {
tls13BasicKeyExMode = TLS13_KE_MODE_PSK_ONLY;
} else if (kxCtx->peerPubkey != NULL) {
tls13BasicKeyExMode = TLS13_CERT_AUTH_WITH_DHE;
} else {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17067, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"psk and peerPubkey are null", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_INTERNAL_EXCEPTION);
return HITLS_INTERNAL_EXCEPTION;
}
ctx->negotiatedInfo.tls13BasicKeyExMode = tls13BasicKeyExMode;
return HITLS_SUCCESS;
}
static int32_t Tls13ServerProcessClientHello(TLS_Ctx *ctx, HS_Msg *msg)
{
int32_t ret = HITLS_SUCCESS;
ClientHelloMsg *clientHello = &msg->body.clientHello;
ctx->method.ctrlCCS(ctx, CCS_CMD_RECV_READY);
bool isNeedSendHrr = false;
if (ctx->hsCtx->readSubState == TLS_PROCESS_STATE_A) {
ret = Tls13ServerCheckClientHello(ctx, clientHello, &isNeedSendHrr);
if (ret != HITLS_SUCCESS) {
return ret;
}
ctx->hsCtx->readSubState = TLS_PROCESS_STATE_B;
}
if (ctx->hsCtx->readSubState == TLS_PROCESS_STATE_B) {
ret = Tls13ServerPostCheckClientHello(ctx, clientHello, &isNeedSendHrr);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17056, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"PostProcessClientHello fail.", 0, 0, 0, 0);
return ret;
}
if (isNeedSendHrr) {
return HS_ChangeState(ctx, TRY_SEND_HELLO_RETRY_REQUEST);
}
ret = UpdateServerBaseKeyExMode(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#if defined(HITLS_TLS_FEATURE_PHA) && defined(HITLS_TLS_FEATURE_CERT_MODE_CLIENT_VERIFY)
TLS_Config *tlsConfig = &ctx->config.tlsConfig;
if (ctx->phaState == PHA_NONE && tlsConfig->isSupportClientVerify &&
msg->body.clientHello.extension.flag.havePostHsAuth) {
ctx->phaState = PHA_EXTENSION;
}
#endif
return HS_ChangeState(ctx, TRY_SEND_SERVER_HELLO);
}
int32_t Tls13ServerRecvClientHelloProcess(TLS_Ctx *ctx, HS_Msg *msg)
{
int32_t ret = 0;
uint16_t selectedVersion = 0;
ClientHelloMsg *clientHello = &msg->body.clientHello;
if (ctx->hsCtx->readSubState == TLS_PROCESS_STATE_A) {
#ifdef HITLS_TLS_FEATURE_CLIENT_HELLO_CB
ret = ClientHelloCbCheck(ctx);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
ret = SelectVersion(ctx, clientHello, &selectedVersion);
if (ret != HITLS_SUCCESS) {
return ret;
}
* supported_versions extension cannot be sent */
clientHello->version = selectedVersion;
}
switch (clientHello->version) {
#ifdef HITLS_TLS_PROTO_TLS_BASIC
case HITLS_VERSION_TLCP_DTLCP11:
case HITLS_VERSION_TLS12:
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15251, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"tls1.3 server receive a 0x%x clientHello.", clientHello->version, 0, 0, 0);
return ServerRecvClientHelloProcess(ctx, msg, false);
#endif
case HITLS_VERSION_TLS13:
return Tls13ServerProcessClientHello(ctx, msg);
default:
break;
}
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_VERSION);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15252, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"server select an unsupported version.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_UNSUPPORT_VERSION;
}
#endif
#endif