* 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 <string.h>
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_err_internal.h"
#include "tls_binlog_id.h"
#include "tls.h"
#include "hitls_error.h"
#include "hitls_security.h"
#include "cipher_suite.h"
#include "hs_ctx.h"
#include "pack_common.h"
#include "pack_extensions.h"
#include "hs_common.h"
#define CIPHER_SUITES_LEN_SIZE 2u
#ifdef HITLS_TLS_PROTO_DTLS12
static int32_t PackClientCookie(PackPacket *pkt, const uint8_t *cookie, uint8_t cookieLen)
{
int32_t ret = PackAppendUint8ToBuf(pkt, cookieLen);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (cookieLen == 0u) {
return HITLS_SUCCESS;
}
return PackAppendDataToBuf(pkt, cookie, cookieLen);
}
#endif
static int32_t PackCipherSuites(const TLS_Ctx *ctx, PackPacket *pkt, bool isTls13)
{
uint16_t *cipherSuites = NULL;
uint32_t cipherSuitesSize = 0;
#ifdef HITLS_TLS_PROTO_TLS13
if (isTls13) {
cipherSuites = ctx->config.tlsConfig.tls13CipherSuites;
cipherSuitesSize = ctx->config.tlsConfig.tls13cipherSuitesSize;
} else {
cipherSuites = ctx->config.tlsConfig.cipherSuites;
cipherSuitesSize = ctx->config.tlsConfig.cipherSuitesSize;
}
#else
(void)isTls13;
cipherSuites = ctx->config.tlsConfig.cipherSuites;
cipherSuitesSize = ctx->config.tlsConfig.cipherSuitesSize;
#endif
int32_t ret = HITLS_SUCCESS;
for (uint32_t i = 0; i < cipherSuitesSize; i++) {
if (!IsCipherSuiteAllowed(ctx, cipherSuites[i], false)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15845, BSL_LOG_LEVEL_WARN, BSL_LOG_BINLOG_TYPE_RUN,
"The cipher suite [0x%04x] is NOT supported, index=[%u].", cipherSuites[i], i, 0, 0);
continue;
}
ret = PackAppendUint16ToBuf(pkt, cipherSuites[i]);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
return HITLS_SUCCESS;
}
static int32_t PackScsvCipherSuites(const TLS_Ctx *ctx, PackPacket *pkt)
{
int32_t ret = HITLS_SUCCESS;
if (!ctx->negotiatedInfo.isRenegotiation) {
ret = PackAppendUint16ToBuf(pkt, TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#ifdef HITLS_TLS_FEATURE_MODE_FALL_BACK_SCSV
if ((ctx->config.tlsConfig.modeSupport & HITLS_MODE_SEND_FALLBACK_SCSV) != 0) {
ret = PackAppendUint16ToBuf(pkt, TLS_FALLBACK_SCSV);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
#endif
return HITLS_SUCCESS;
}
static int32_t PackClientCipherSuites(const TLS_Ctx *ctx, PackPacket *pkt)
{
uint32_t cipherLenPosition = 0u;
int32_t ret = PackStartLengthField(pkt, CIPHER_SUITES_LEN_SIZE, &cipherLenPosition);
if (ret != HITLS_SUCCESS) {
return ret;
}
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->config.tlsConfig.maxVersion == HITLS_VERSION_TLS13) {
ret = PackCipherSuites(ctx, pkt, 1);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16925, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"PackCipherSuites fail", 0, 0, 0, 0);
return ret;
}
}
#endif
if (ctx->config.tlsConfig.minVersion != HITLS_VERSION_TLS13) {
ret = PackCipherSuites(ctx, pkt, 0);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16926, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"PackCipherSuites fail", 0, 0, 0, 0);
return ret;
}
}
uint32_t suitesLength = 0;
ret = PackGetSubBuffer(pkt, cipherLenPosition, &suitesLength, NULL);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (suitesLength == CIPHER_SUITES_LEN_SIZE) {
BSL_ERR_PUSH_ERROR(HITLS_PACK_CLIENT_CIPHER_SUITE_ERR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15732, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"pack cipher suite error, no cipher suite.", 0, 0, 0, 0);
return HITLS_PACK_CLIENT_CIPHER_SUITE_ERR;
}
ret = PackScsvCipherSuites(ctx, pkt);
if (ret != HITLS_SUCCESS) {
return ret;
}
* be calculated according to offset */
PackCloseUint16Field(pkt, cipherLenPosition);
return HITLS_SUCCESS;
}
static int32_t PackClientCompressionMethod(PackPacket *pkt)
{
int32_t ret = PackAppendUint8ToBuf(pkt, 1);
if (ret != HITLS_SUCCESS) {
return ret;
}
return PackAppendUint8ToBuf(pkt, 0);
}
static int32_t PackClientHelloMandatoryField(const TLS_Ctx *ctx, PackPacket *pkt)
{
int32_t ret = HITLS_SUCCESS;
const TLS_Config *tlsConfig = &ctx->config.tlsConfig;
if (ctx->hsCtx->clientRandom == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16927, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"clientRandom null", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_NULL_INPUT);
return HITLS_NULL_INPUT;
}
uint16_t version =
#ifdef HITLS_TLS_PROTO_TLS13
(tlsConfig->maxVersion == HITLS_VERSION_TLS13) ? HITLS_VERSION_TLS12 :
#endif
tlsConfig->maxVersion;
ret = PackHelloCommonField(ctx, pkt, version, true);
if (ret != HITLS_SUCCESS) {
return ret;
}
#ifdef HITLS_TLS_PROTO_DTLS12
if (IS_SUPPORT_DATAGRAM(tlsConfig->originVersionMask)) {
ret = PackClientCookie(pkt, ctx->negotiatedInfo.cookie, (uint8_t)ctx->negotiatedInfo.cookieSize);
if (ret != HITLS_SUCCESS) {
memset(ctx->negotiatedInfo.cookie, 0, ctx->negotiatedInfo.cookieSize);
return ret;
}
}
#endif
ret = PackClientCipherSuites(ctx, pkt);
if (ret != HITLS_SUCCESS) {
return ret;
}
return PackClientCompressionMethod(pkt);
}
int32_t PackClientHello(const TLS_Ctx *ctx, PackPacket *pkt)
{
int32_t ret = PackClientHelloMandatoryField(ctx, pkt);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15735, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"pack client hello mandatory content fail.", 0, 0, 0, 0);
return ret;
}
ret = PackClientExtension(ctx, pkt);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15736, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"pack client hello extension content fail.", 0, 0, 0, 0);
return ret;
}
return HITLS_SUCCESS;
}
#endif