* 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 <string.h>
#include "hitls_build.h"
#include "bsl_bytes.h"
#include "bsl_sal.h"
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_err_internal.h"
#include "hitls.h"
#include "hitls_error.h"
#include "tls_config.h"
#include "bsl_errno.h"
#include "bsl_uio.h"
#ifdef HITLS_TLS_FEATURE_INDICATOR
#include "indicator.h"
#endif
#ifdef HITLS_TLS_FEATURE_SECURITY
#include "security.h"
#endif
#include "record.h"
#include "hs_kx.h"
#include "hs.h"
#include "hs_extensions.h"
#include "config_type.h"
#include "config_check.h"
#include "hs_common.h"
#ifdef HITLS_TLS_PROTO_DTLS12
#define DTLS_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
#endif
#ifdef HITLS_TLS_FEATURE_EXPORT_KEY_MATERIAL
#define LABEL_SIZE 5
#define MAX_LABEL_SIZE 23
#endif
#ifdef HITLS_TLS_PROTO_TLS13
const uint8_t g_hrrRandom[HS_RANDOM_SIZE] = {
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
};
const uint8_t *HS_GetHrrRandom(uint32_t *len)
{
*len = HS_RANDOM_SIZE;
return g_hrrRandom;
}
#ifdef HITLS_TLS_PROTO_TLS_BASIC
const uint8_t g_tls12Downgrade[HS_DOWNGRADE_RANDOM_SIZE] = {
0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01
};
const uint8_t *HS_GetTls12DowngradeRandom(uint32_t *len)
{
*len = HS_DOWNGRADE_RANDOM_SIZE;
return g_tls12Downgrade;
}
#endif
#endif
#ifdef HITLS_BSL_LOG
static const char *g_stateMachineStr[] = {
[TLS_IDLE] = "idle",
[TLS_CONNECTED] = "connected",
#ifdef HITLS_TLS_HOST_CLIENT
[TRY_SEND_CLIENT_HELLO] = "send client hello",
[TRY_SEND_CLIENT_KEY_EXCHANGE] = "send client key exchange",
[TRY_RECV_SERVER_HELLO] = "recv server hello",
#ifdef HITLS_TLS_PROTO_DTLS12
[TRY_RECV_HELLO_VERIFY_REQUEST] = "recv hello verify request",
#endif
[TRY_RECV_SERVER_KEY_EXCHANGE] = "recv server key exchange",
[TRY_RECV_SERVER_HELLO_DONE] = "recv server hello done",
[TRY_RECV_NEW_SESSION_TICKET] = "recv new session ticket",
[TRY_RECV_HELLO_REQUEST] = "recv hello request",
#endif
#ifdef HITLS_TLS_HOST_SERVER
[TRY_SEND_HELLO_REQUEST] = "send hello request",
[TRY_SEND_SERVER_HELLO] = "send server hello",
#ifdef HITLS_TLS_PROTO_DTLS12
[TRY_SEND_HELLO_VERIFY_REQUEST] = "send hello verify request",
#endif
[TRY_SEND_SERVER_KEY_EXCHANGE] = "send server key exchange",
[TRY_RECV_CLIENT_HELLO] = "recv client hello",
[TRY_RECV_CLIENT_KEY_EXCHANGE] = "recv client key exchange",
[TRY_SEND_SERVER_HELLO_DONE] = "send server hello done",
[TRY_SEND_NEW_SESSION_TICKET] = "send new session ticket",
#endif
#ifdef HITLS_TLS_PROTO_TLS13
[TRY_RECV_KEY_UPDATE] = "recv keyupdate",
[TRY_SEND_KEY_UPDATE] = "send keyupdate",
#ifdef HITLS_TLS_HOST_CLIENT
[TRY_RECV_ENCRYPTED_EXTENSIONS] = "recv encrypted extensions",
[TRY_SEND_END_OF_EARLY_DATA] = "send end of early data",
#endif
#ifdef HITLS_TLS_HOST_SERVER
[TRY_SEND_ENCRYPTED_EXTENSIONS] = "send encrypted extensions",
[TRY_SEND_HELLO_RETRY_REQUEST] = "send hello retry request",
[TRY_RECV_END_OF_EARLY_DATA] = "recv end of early data",
#endif
#endif
[TRY_SEND_CERTIFICATE] = "send certificate",
[TRY_SEND_CERTIFICATE_REQUEST] = "send certificate request",
[TRY_SEND_CERTIFICATE_VERIFY] = "send certificate verify",
[TRY_SEND_CHANGE_CIPHER_SPEC] = "send change cipher spec",
[TRY_RECV_CERTIFICATE] = "recv certificate",
[TRY_RECV_CERTIFICATE_REQUEST] = "recv certificate request",
[TRY_RECV_CERTIFICATE_VERIFY] = "recv certificate verify",
[TRY_RECV_FINISH] = "recv finished",
[TRY_SEND_FINISH] = "send finished",
};
const char *HS_GetStateStr(uint32_t state)
{
if ((state >= (sizeof(g_stateMachineStr) / sizeof(char *))) || (g_stateMachineStr[state] == NULL)) {
return "unknown";
}
return g_stateMachineStr[state];
}
const char *HS_GetMsgTypeStr(HS_MsgType type)
{
switch (type) {
case HELLO_REQUEST:
return "hello request";
case CLIENT_HELLO:
return "client hello";
case SERVER_HELLO:
return "server hello";
#ifdef HITLS_TLS_PROTO_TLS13
case ENCRYPTED_EXTENSIONS:
return "encrypted extensions";
#endif
case CERTIFICATE:
return "certificate";
case SERVER_KEY_EXCHANGE:
return "server key exchange";
case CERTIFICATE_REQUEST:
return "certificate request";
case SERVER_HELLO_DONE:
return "server hello done";
case CERTIFICATE_VERIFY:
return "certificate verify";
case CLIENT_KEY_EXCHANGE:
return "client key exchange";
case NEW_SESSION_TICKET:
return "new session ticket";
case FINISHED:
return "finished";
default:
break;
}
return "unknown";
}
#endif
int32_t HS_ChangeState(TLS_Ctx *ctx, uint32_t nextState)
{
HS_Ctx *hsCtx = (HS_Ctx *)ctx->hsCtx;
hsCtx->state = nextState;
#ifdef HITLS_TLS_FEATURE_MODE_RELEASE_BUFFERS
if ((ctx->config.tlsConfig.modeSupport & HITLS_MODE_RELEASE_BUFFERS) != 0) {
if (hsCtx->state == TLS_CONNECTED) {
RecTryFreeRecBuf(ctx, false);
RecTryFreeRecBuf(ctx, true);
} else if (IsHsSendState(hsCtx->state)) {
RecTryFreeRecBuf(ctx, false);
} else {
RecTryFreeRecBuf(ctx, true);
}
}
#endif
the hsCtx initiation */
if (ctx->state != CM_STATE_TRANSPORTING) {
BSL_LOG_BINLOG_VARLEN(BINLOG_ID15573, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
"handshake state machine change to:%s.", HS_GetStateStr(nextState));
}
return HITLS_SUCCESS;
}
int32_t HS_CombineRandom(const uint8_t *random1, const uint8_t *random2, uint32_t randomSize,
uint8_t *dest, uint32_t destSize)
{
* error code. */
if ((randomSize == 0u) || (destSize < randomSize * 2)) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_RANDOM_SIZE_ERR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15574, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"invalid randomSize for combine random.", 0, 0, 0, 0);
return HITLS_MSG_HANDLE_RANDOM_SIZE_ERR;
}
memcpy(dest, random1, randomSize);
memcpy(&dest[randomSize], random2, randomSize);
return HITLS_SUCCESS;
}
#ifdef HITLS_TLS_PROTO_TLCP11
uint8_t *HS_PrepareSignDataTlcp(const TLS_Ctx *ctx, const uint8_t *partSignData, uint32_t partSignDataLen,
uint32_t *signDataLen)
{
* data/encryption certificate */
uint32_t exchParamLen = 3;
uint32_t randomLen = HS_RANDOM_SIZE * 2u;
uint32_t dataLen = randomLen + partSignDataLen + exchParamLen;
uint8_t *data = BSL_SAL_Calloc(1u, dataLen);
if (data == NULL) {
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15577, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"signature data memory alloc fail.", 0, 0, 0, 0);
return NULL;
}
memcpy(data, ctx->hsCtx->clientRandom, HS_RANDOM_SIZE);
memcpy(&data[HS_RANDOM_SIZE], ctx->hsCtx->serverRandom, HS_RANDOM_SIZE);
BSL_Uint24ToByte(partSignDataLen, &data[randomLen]);
memcpy(&data[randomLen] + exchParamLen, partSignData, partSignDataLen);
*signDataLen = dataLen;
return data;
}
#endif
uint8_t *HS_PrepareSignData(const TLS_Ctx *ctx, const uint8_t *partSignData,
uint32_t partSignDataLen, uint32_t *signDataLen)
{
uint32_t randomLen = HS_RANDOM_SIZE * 2u;
uint32_t dataLen = randomLen + partSignDataLen;
uint8_t *data = BSL_SAL_Calloc(1u, dataLen);
if (data == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16813, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "Calloc fail", 0, 0, 0, 0);
BSL_ERR_PUSH_ERROR(HITLS_INTERNAL_EXCEPTION);
return NULL;
}
memcpy(data, ctx->hsCtx->clientRandom, HS_RANDOM_SIZE);
memcpy(&data[HS_RANDOM_SIZE], ctx->hsCtx->serverRandom, HS_RANDOM_SIZE);
memcpy(&data[randomLen], partSignData, partSignDataLen);
*signDataLen = dataLen;
return data;
}
#if defined(HITLS_TLS_PROTO_DTLS12) && defined(HITLS_BSL_UIO_SCTP)
* @brief Calculate the sctp auth key
* @details auth key: PRF(SecurityParameters.master_secret, label,
* SecurityParameters.client_random +
* SecurityParameters.server_random)[length]
*
* @param ctx [IN] TLS context
* @param authKey [OUT] Authorization key
* @param authKeyLen [IN] Key length
*
* @retval HITLS_SUCCESS calculation is complete.
* @retval HITLS_MSG_HANDLE_RANDOM_SIZE_ERR The random number length is incorrect.
* @retval For other error codes, see SAL_CRYPT_PRF.
*/
int32_t CalcSctpAuthKey(const TLS_Ctx *ctx, uint8_t *authKey, uint32_t authKeyLen)
{
int32_t ret;
uint8_t randomValue[HS_RANDOM_SIZE * 2] = {0};
uint32_t randomValueSize = HS_RANDOM_SIZE * 2;
HS_Ctx *hsCtx = (HS_Ctx *)ctx->hsCtx;
ret = HS_CombineRandom(hsCtx->clientRandom, hsCtx->serverRandom, HS_RANDOM_SIZE, randomValue, randomValueSize);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15579, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"combine random fail.", 0, 0, 0, 0);
return ret;
}
CRYPT_KeyDeriveParameters deriveInfo;
deriveInfo.hashAlgo = ctx->negotiatedInfo.cipherSuiteInfo.hashAlg;
deriveInfo.secret = hsCtx->masterKey;
deriveInfo.secretLen = MASTER_SECRET_LEN;
deriveInfo.label = (const uint8_t *)DTLS_SCTP_AUTH_LABEL;
deriveInfo.labelLen = strlen(DTLS_SCTP_AUTH_LABEL);
deriveInfo.seed = randomValue;
deriveInfo.seedLen = randomValueSize;
deriveInfo.libCtx = LIBCTX_FROM_CTX(ctx);
deriveInfo.attrName = ATTRIBUTE_FROM_CTX(ctx);
ret = SAL_CRYPT_PRF(&deriveInfo, authKey, authKeyLen);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15580, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"SAL_CRYPT_PRF fail when calc sctp auth key.", 0, 0, 0, 0);
}
return ret;
}
int32_t HS_SetSctpAuthKey(TLS_Ctx *ctx)
{
if (!BSL_UIO_GetUioChainTransportType(ctx->uio, BSL_UIO_SCTP)) {
return HITLS_SUCCESS;
}
int32_t ret;
uint8_t authKey[DTLS_SCTP_SHARED_AUTHKEY_LEN] = {0};
uint16_t authKeyLen = sizeof(authKey);
ret = CalcSctpAuthKey(ctx, authKey, authKeyLen);
if (ret != HITLS_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15581, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"calc sctp auth key failed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return ret;
}
is invoked again */
ret = BSL_UIO_Ctrl(ctx->uio, BSL_UIO_SCTP_ADD_AUTH_SHARED_KEY, (int32_t)authKeyLen, authKey);
BSL_SAL_CleanseData(authKey, DTLS_SCTP_SHARED_AUTHKEY_LEN);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(HITLS_UIO_SCTP_ADD_AUTH_KEY_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15582, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"uio add sctp auth shared key failed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_UIO_SCTP_ADD_AUTH_KEY_FAIL;
}
return HITLS_SUCCESS;
}
int32_t HS_ActiveSctpAuthKey(TLS_Ctx *ctx)
{
if (!BSL_UIO_GetUioChainTransportType(ctx->uio, BSL_UIO_SCTP)) {
return HITLS_SUCCESS;
}
int32_t ret = BSL_UIO_Ctrl(ctx->uio, BSL_UIO_SCTP_ACTIVE_AUTH_SHARED_KEY, 0, NULL);
if (ret != BSL_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15583, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"next sctp auth key error.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
return HITLS_UIO_SCTP_ACTIVE_AUTH_KEY_FAIL;
}
return HITLS_SUCCESS;
}
int32_t HS_DeletePreviousSctpAuthKey(TLS_Ctx *ctx)
{
if (!BSL_UIO_GetUioChainTransportType(ctx->uio, BSL_UIO_SCTP)) {
return HITLS_SUCCESS;
}
int32_t ret = BSL_UIO_Ctrl(ctx->uio, BSL_UIO_SCTP_DEL_PRE_AUTH_SHARED_KEY, 0, NULL);
if (ret != BSL_SUCCESS) {
ret = HITLS_UIO_SCTP_DEL_AUTH_KEY_FAIL;
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15584, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"uio delete sctp auth shared key failed.", 0, 0, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
}
return ret;
}
#endif
bool IsNeedServerKeyExchange(const TLS_Ctx *ctx)
{
HITLS_KeyExchAlgo kxAlg = ctx->negotiatedInfo.cipherSuiteInfo.kxAlg;
* the ServerKeyExchange message
*/
if ((kxAlg == HITLS_KEY_EXCH_PSK) || (kxAlg == HITLS_KEY_EXCH_RSA_PSK)) {
if (ctx->isClient) {
return true;
} else {
if (ctx->config.tlsConfig.pskIdentityHint != NULL) {
return true;
}
return false;
}
}
#ifdef HITLS_TLS_PROTO_TLCP11
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLCP_DTLCP11) {
return true;
}
#endif
* is not required. */
return ((kxAlg != HITLS_KEY_EXCH_ECDH) && (kxAlg != HITLS_KEY_EXCH_DH) && (kxAlg != HITLS_KEY_EXCH_RSA));
}
bool IsNeedCertPrepare(const CipherSuiteInfo *cipherSuiteInfo)
{
if (cipherSuiteInfo == NULL) {
return false;
}
switch (cipherSuiteInfo->kxAlg) {
case HITLS_KEY_EXCH_PSK:
case HITLS_KEY_EXCH_DHE_PSK:
case HITLS_KEY_EXCH_ECDHE_PSK:
return false;
default:
break;
}
switch (cipherSuiteInfo->authAlg) {
case HITLS_AUTH_NULL:
return false;
default:
break;
}
return true;
}
bool IsTicketSupport(const TLS_Ctx *ctx)
{
#ifdef HITLS_TLS_FEATURE_SESSION_TICKET
if (ctx->config.tlsConfig.isSupportSessionTicket
#ifdef HITLS_TLS_FEATURE_SECURITY
&& (SECURITY_SslCheck(ctx, HITLS_SECURITY_SECOP_TICKET, 0, 0, NULL) == SECURITY_SUCCESS)
#endif
) {
return true;
}
#endif
(void)ctx;
return false;
}
#ifdef HITLS_TLS_FEATURE_PSK
bool IsPskNegotiation(const TLS_Ctx *ctx)
{
HITLS_KeyExchAlgo kxAlg = ctx->negotiatedInfo.cipherSuiteInfo.kxAlg;
return ((kxAlg == HITLS_KEY_EXCH_ECDHE_PSK) || (kxAlg == HITLS_KEY_EXCH_DHE_PSK) ||
(kxAlg == HITLS_KEY_EXCH_RSA_PSK) || (kxAlg == HITLS_KEY_EXCH_PSK));
}
int32_t CheckClientPsk(TLS_Ctx *ctx)
{
uint8_t psk[HS_PSK_MAX_LEN] = {0};
uint8_t identity[HS_PSK_IDENTITY_MAX_LEN + 1] = {0};
if (ctx->hsCtx->kxCtx->pskInfo != NULL && ctx->hsCtx->kxCtx->pskInfo->psk != NULL) {
return HITLS_SUCCESS;
}
if (ctx->config.tlsConfig.pskClientCb == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_UNREGISTERED_CALLBACK, BINLOG_ID16815, "unregistered pskClientCb");
}
uint32_t pskUsedLen = ctx->config.tlsConfig.pskClientCb(ctx, NULL, identity, HS_PSK_IDENTITY_MAX_LEN,
psk, HS_PSK_MAX_LEN);
if (pskUsedLen == 0 || pskUsedLen > HS_PSK_IDENTITY_MAX_LEN) {
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MSG_HANDLE_ILLEGAL_PSK_LEN, BINLOG_ID16816, "pskUsedLen incorrect");
}
uint32_t identityUsedLen = (uint32_t)strnlen((char *)identity, HS_PSK_IDENTITY_MAX_LEN + 1);
if (identityUsedLen > HS_PSK_IDENTITY_MAX_LEN) {
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
return HITLS_MSG_HANDLE_ILLEGAL_IDENTITY_LEN;
}
if (ctx->hsCtx->kxCtx->pskInfo == NULL) {
ctx->hsCtx->kxCtx->pskInfo = (PskInfo *)BSL_SAL_Calloc(1u, sizeof(PskInfo));
if (ctx->hsCtx->kxCtx->pskInfo == NULL) {
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID16694, "Calloc fail");
}
}
uint8_t *tmpIdentity = NULL;
if (identityUsedLen > 0) {
tmpIdentity = (uint8_t *)BSL_SAL_Calloc(1u, (identityUsedLen + 1));
if (tmpIdentity == NULL) {
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID16817, "Calloc fail");
}
memcpy(tmpIdentity, identity, identityUsedLen);
}
ctx->hsCtx->kxCtx->pskInfo->psk = (uint8_t *)BSL_SAL_Dump(psk, pskUsedLen);
BSL_SAL_CleanseData(psk, HS_PSK_MAX_LEN);
if (ctx->hsCtx->kxCtx->pskInfo->psk == NULL) {
BSL_SAL_FREE(tmpIdentity);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID16818, "Dump fail");
}
ctx->hsCtx->kxCtx->pskInfo->pskLen = pskUsedLen;
if (tmpIdentity != NULL) {
BSL_SAL_FREE(ctx->hsCtx->kxCtx->pskInfo->identity);
ctx->hsCtx->kxCtx->pskInfo->identity = tmpIdentity;
ctx->hsCtx->kxCtx->pskInfo->identityLen = identityUsedLen;
}
return HITLS_SUCCESS;
}
#endif
uint32_t HS_GetState(const TLS_Ctx *ctx)
{
if (ctx->hsCtx == NULL) {
return HS_STATE_BUTT;
}
return ctx->hsCtx->state;
}
#ifdef HITLS_TLS_FEATURE_SNI
const char *HS_GetServerName(const TLS_Ctx *ctx)
{
if (ctx == NULL || ctx->negotiatedInfo.serverName == NULL) {
return NULL;
}
return (char *)ctx->negotiatedInfo.serverName;
}
#endif
int32_t HS_GrowMsgBuf(TLS_Ctx *ctx, uint32_t msgSize, bool keepOldData)
{
if (msgSize <= ctx->hsCtx->bufferLen) {
return HITLS_SUCCESS;
}
uint32_t bufSize = ctx->hsCtx->bufferLen;
uint32_t oldDataSize = bufSize;
uint8_t *oldDataAddr = ctx->hsCtx->msgBuf;
while (bufSize != 0 && bufSize < msgSize) {
bufSize = bufSize << 1;
}
ctx->hsCtx->msgBuf = BSL_SAL_Calloc(1u, bufSize);
if (ctx->hsCtx->msgBuf == NULL) {
ctx->hsCtx->msgBuf = oldDataAddr;
BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15935, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"msgBuf malloc fail while get reass msg.", 0, 0, 0, 0);
return HITLS_MEMALLOC_FAIL;
}
ctx->hsCtx->bufferLen = bufSize;
if (keepOldData) {
memcpy(ctx->hsCtx->msgBuf, oldDataAddr, oldDataSize);
}
BSL_SAL_FREE(oldDataAddr);
return HITLS_SUCCESS;
}
int32_t HS_ReSizeMsgBuf(TLS_Ctx *ctx, uint32_t msgSize)
{
bool keepOldData = false;
return HS_GrowMsgBuf(ctx, msgSize, keepOldData);
}
uint32_t HS_MaxMessageSize(TLS_Ctx *ctx, HS_MsgType type)
{
switch (type) {
case HELLO_REQUEST:
return HITLS_HELLO_REQUEST_MAX_SIZE;
case CLIENT_HELLO:
return HITLS_CLIENT_HELLO_MAX_SIZE;
#ifdef HITLS_TLS_PROTO_DTLS12
case HELLO_VERIFY_REQUEST:
return HITLS_HELLO_VERIFY_REQUEST_MAX_SIZE;
#endif
case SERVER_HELLO:
return HITLS_SERVER_HELLO_MAX_SIZE;
#ifdef HITLS_TLS_PROTO_TLS13
case ENCRYPTED_EXTENSIONS:
return HITLS_ENCRYPTED_EXTENSIONS_MAX_SIZE;
#endif
case SERVER_KEY_EXCHANGE:
return HITLS_SERVER_KEY_EXCH_MAX_SIZE;
case CERTIFICATE:
case CERTIFICATE_REQUEST:
return ctx->config.tlsConfig.maxCertList == 0 ? HITLS_MAX_CERT_LIST_DEFAULT
: ctx->config.tlsConfig.maxCertList;
case SERVER_HELLO_DONE:
return HITLS_SERVER_HELLO_DONE_MAX_SIZE;
case CLIENT_KEY_EXCHANGE:
return HITLS_CLIENT_KEY_EXCH_MAX_SIZE;
case CERTIFICATE_VERIFY:
return MAX_CERT_VERIFY_SIZE;
case NEW_SESSION_TICKET:
#ifdef HITLS_TLS_PROTO_TLS13
if (GET_VERSION_FROM_CTX(ctx) == HITLS_VERSION_TLS13) {
return HITLS_SESSION_TICKET_MAX_SIZE_TLS13;
}
#endif
return HITLS_SESSION_TICKET_MAX_SIZE_TLS12;
#ifdef HITLS_TLS_PROTO_TLS13
case END_OF_EARLY_DATA:
return HITLS_END_OF_EARLY_DATA_MAX_SIZE;
#endif
case FINISHED:
return HITLS_FINISHED_MAX_SIZE;
#ifdef HITLS_TLS_PROTO_TLS13
case KEY_UPDATE:
return HITLS_KEY_UPDATE_MAX_SIZE;
#endif
default:
return 0;
}
}
#ifdef HITLS_TLS_PROTO_TLS13
uint32_t HS_GetBinderLen(HITLS_Session *session, HITLS_HashAlgo *hashAlg)
{
if (*hashAlg != HITLS_HASH_BUTT) {
return SAL_CRYPT_HmacSize(*hashAlg);
}
if (session == NULL) {
return 0;
}
uint16_t cipherSuite = 0;
int32_t ret = HITLS_SESS_GetCipherSuite(session, &cipherSuite);
if (ret != HITLS_SUCCESS) {
return 0;
}
CipherSuiteInfo cipherInfo = {0};
ret = CFG_GetCipherSuiteInfo(cipherSuite, &cipherInfo);
if (ret != HITLS_SUCCESS) {
BSL_ERR_PUSH_ERROR(ret);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16819, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"GetCipherSuiteInfo fail", 0, 0, 0, 0);
return 0;
}
*hashAlg = cipherInfo.hashAlg;
return SAL_CRYPT_HmacSize(*hashAlg);
}
#endif
#ifdef HITLS_TLS_FEATURE_EXPORT_KEY_MATERIAL
The exporter value is computed as:
TLS-Exporter(label, context_value, key_length) =
HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
"exporter", Hash(context_value), key_length) */
#ifdef HITLS_TLS_PROTO_TLS13
static int32_t Tls13ExportKeyingMaterial(HITLS_Ctx *ctx, uint8_t *out, size_t outLen,
const char *label, size_t labelLen, const uint8_t *context, size_t contextLen, int32_t useContext)
{
size_t useContextLen = contextLen;
if (useContext == 0) {
useContextLen = 0;
}
uint8_t tmpSecret[MAX_DIGEST_SIZE] = {0};
HITLS_HashAlgo hash = ctx->negotiatedInfo.cipherSuiteInfo.hashAlg;
uint32_t hashLen = SAL_CRYPT_DigestSize(hash);
if (hashLen == 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16820, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "DigestSize err", 0, 0, 0, 0);
return HITLS_CRYPT_ERR_DIGEST;
}
CRYPT_KeyDeriveParameters deriveInfo = {0};
deriveInfo.hashAlgo = hash;
deriveInfo.secret = ctx->exporterMasterSecret;
deriveInfo.secretLen = hashLen;
deriveInfo.label = (const uint8_t *)label;
deriveInfo.labelLen = (uint32_t)labelLen;
deriveInfo.seed = NULL;
deriveInfo.seedLen = 0;
deriveInfo.libCtx = LIBCTX_FROM_CTX(ctx);
deriveInfo.attrName = ATTRIBUTE_FROM_CTX(ctx);
int32_t ret = HS_TLS13DeriveSecret(&deriveInfo, false, tmpSecret, hashLen);
if (ret != HITLS_SUCCESS) {
BSL_SAL_CleanseData(tmpSecret, MAX_DIGEST_SIZE);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16821, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"DeriveSecret fail", 0, 0, 0, 0);
return ret;
}
const uint8_t exportLabel[] = "exporter";
deriveInfo.secret = tmpSecret;
deriveInfo.secretLen = hashLen;
deriveInfo.label = exportLabel;
deriveInfo.labelLen = sizeof(exportLabel) - 1;
deriveInfo.seed = context;
deriveInfo.seedLen = (uint32_t)useContextLen;
ret = HS_TLS13DeriveSecret(&deriveInfo, false, out, (uint32_t)outLen);
BSL_SAL_CleanseData(tmpSecret, MAX_DIGEST_SIZE);
return ret;
}
#endif
static bool IsSpecialLabel(const char *label, size_t labelLen)
{
const char labelArray[LABEL_SIZE][MAX_LABEL_SIZE] = {
"client finished",
"server finished",
"key expansion",
"master secret",
"extended master secret"};
char labelBuf[MAX_LABEL_SIZE] = { 0 };
size_t useLabelLen = labelLen;
if (labelLen > MAX_LABEL_SIZE) {
useLabelLen = MAX_LABEL_SIZE;
}
if (labelLen != 0 && useLabelLen <= sizeof(labelBuf)) {
memcpy(labelBuf, label, useLabelLen);
} else if (labelLen != 0) {
return true;
}
for (uint32_t index = 0; index < LABEL_SIZE; index++) {
if (memcmp(labelBuf, labelArray[index], MAX_LABEL_SIZE) == 0) {
return true;
}
}
return false;
}
If no context is provided, it then computes:
PRF(SecurityParameters.master_secret, label,
SecurityParameters.client_random +
SecurityParameters.server_random
)[length]
If context is provided, it computes:
PRF(SecurityParameters.master_secret, label,
SecurityParameters.client_random +
SecurityParameters.server_random +
context_value_length + context_value
)[length] */
static int32_t Tls12ExportKeyingMaterial(HITLS_Ctx *ctx, uint8_t *out, size_t outLen,
const char *label, size_t labelLen, const uint8_t *context, size_t contextLen, int32_t useContext)
{
if (IsSpecialLabel(label, labelLen)) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_INVALID_INPUT, BINLOG_ID16822, "input invalid");
}
size_t seedLen = RANDOM_SIZE * 2;
if (useContext != 0) {
seedLen += sizeof(uint16_t) + contextLen;
}
uint8_t *seed = BSL_SAL_Calloc((uint32_t)seedLen, sizeof(uint8_t));
if (seed == NULL) {
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID16823, "Calloc fail");
}
size_t usedLen = 0;
memcpy(seed + usedLen, ctx->negotiatedInfo.clientRandom, RANDOM_SIZE);
usedLen += RANDOM_SIZE;
memcpy(seed + usedLen, ctx->negotiatedInfo.serverRandom, RANDOM_SIZE);
usedLen += RANDOM_SIZE;
if (useContext != 0) {
BSL_Uint16ToByte((uint16_t)contextLen, seed + usedLen);
usedLen += sizeof(uint16_t);
if (context != NULL && contextLen != 0) {
memcpy(seed + usedLen, context, contextLen);
}
}
uint32_t masterKeyLen = HITLS_SESS_GetMasterKeyLen(ctx->session);
uint8_t *masterKey = BSL_SAL_Calloc(masterKeyLen, sizeof(uint8_t));
if (masterKey == NULL) {
BSL_SAL_FREE(seed);
return RETURN_ERROR_NUMBER_PROCESS(HITLS_MEMALLOC_FAIL, BINLOG_ID16824, "Calloc fail");
}
int32_t ret = HITLS_SESS_GetMasterKey(ctx->session, masterKey, &masterKeyLen);
if (ret != HITLS_SUCCESS) {
BSL_SAL_FREE(seed);
BSL_SAL_FREE(masterKey);
return ret;
}
CRYPT_KeyDeriveParameters deriveInfo = {0};
deriveInfo.hashAlgo = ctx->negotiatedInfo.cipherSuiteInfo.hashAlg;
deriveInfo.secret = masterKey;
deriveInfo.secretLen = masterKeyLen;
deriveInfo.label = (const uint8_t *)label;
deriveInfo.labelLen = (uint32_t)labelLen;
deriveInfo.seed = seed;
deriveInfo.seedLen = (uint32_t)seedLen;
deriveInfo.libCtx = LIBCTX_FROM_CTX(ctx);
deriveInfo.attrName = ATTRIBUTE_FROM_CTX(ctx);
ret = SAL_CRYPT_PRF(&deriveInfo, out, (uint32_t)outLen);
BSL_SAL_FREE(seed);
BSL_SAL_ClearFree(masterKey, masterKeyLen);
return ret;
}
int32_t HITLS_ExportKeyingMaterial(HITLS_Ctx *ctx, uint8_t *out, size_t outLen, const char *label, size_t labelLen,
const uint8_t *context, size_t contextLen, int32_t useContext)
{
if (ctx == NULL || out == NULL || outLen == 0) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16825, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "input null", 0, 0, 0, 0);
return HITLS_INVALID_INPUT;
}
if (useContext != 0 && contextLen != 0 && (contextLen > UINT16_MAX || context == NULL)) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16826, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "input err", 0, 0, 0, 0);
return HITLS_INVALID_INPUT;
}
if (ctx->state != CM_STATE_TRANSPORTING) {
return HITLS_MSG_HANDLE_STATE_ILLEGAL;
}
int32_t ret = 0;
#ifdef HITLS_TLS_PROTO_TLS13
if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
ret = Tls13ExportKeyingMaterial(ctx, out, outLen, label, labelLen, context, contextLen, useContext);
} else
#endif
{
ret = Tls12ExportKeyingMaterial(ctx, out, outLen, label, labelLen, context, contextLen, useContext);
}
return ret;
}
#endif
bool GroupConformToVersion(const TLS_Ctx *ctx, uint16_t version, uint16_t group)
{
uint32_t versionBits = MapVersion2VersionBit(IS_SUPPORT_DATAGRAM(ctx->config.tlsConfig.originVersionMask), version);
const TLS_GroupInfo *groupInfo = ConfigGetGroupInfo(&ctx->config.tlsConfig, group);
if (groupInfo == NULL || ((groupInfo->versionBits & versionBits) != versionBits)) {
return false;
}
#ifdef HITLS_TLS_FEATURE_SECURITY
int32_t ret = SECURITY_SslCheck(ctx, HITLS_SECURITY_SECOP_CURVE_SUPPORTED, 0, (int32_t)group, NULL);
if (ret != SECURITY_SUCCESS) {
return false;
}
#endif
return true;
}
uint16_t *CheckSupportSignAlgorithms(const TLS_Ctx *ctx, const uint16_t *signAlgorithms,
uint32_t signAlgorithmsSize, uint32_t *newSignAlgorithmsSize)
{
(void)ctx;
uint32_t validNum = 0;
uint16_t *retSignAlgorithms = BSL_SAL_Calloc(signAlgorithmsSize, sizeof(uint16_t));
if (retSignAlgorithms == NULL) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17308, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "Calloc fail", 0, 0, 0, 0);
return NULL;
}
for (uint32_t i = 0; i < signAlgorithmsSize; i++) {
#ifdef HITLS_TLS_PROTO_TLS13
const uint32_t dsaMask = 0x02;
const uint32_t sha1Mask = 0x0200;
const uint32_t sha224Mask = 0x0300;
if (ctx->config.tlsConfig.maxVersion == HITLS_VERSION_TLS13 &&
ctx->config.tlsConfig.minVersion == HITLS_VERSION_TLS13) {
if (ctx->isClient &&
(((signAlgorithms[i] & 0xff00) == sha1Mask) ||
((signAlgorithms[i] & 0xff00) == sha224Mask))) {
continue;
}
if (((signAlgorithms[i] & 0xff) == dsaMask) ||
signAlgorithms[i] == CERT_SIG_SCHEME_RSA_PKCS1_SHA1 ||
signAlgorithms[i] == CERT_SIG_SCHEME_RSA_PKCS1_SHA224) {
continue;
}
}
#endif
if (ctx->config.tlsConfig.maxVersion != HITLS_VERSION_TLCP_DTLCP11 &&
ctx->config.tlsConfig.maxVersion != HITLS_VERSION_TLS13 &&
signAlgorithms[i] == CERT_SIG_SCHEME_SM2_SM3) {
continue;
}
#ifdef HITLS_TLS_FEATURE_SECURITY
if (SECURITY_SslCheck(ctx, HITLS_SECURITY_SECOP_SIGALG_CHECK, 0, signAlgorithms[i], NULL) != SECURITY_SUCCESS) {
continue;
}
#endif
retSignAlgorithms[validNum] = signAlgorithms[i];
validNum++;
}
*newSignAlgorithmsSize = validNum;
return retSignAlgorithms;
}
uint32_t HS_GetExtensionTypeId(uint32_t hsExtensionsType)
{
switch (hsExtensionsType) {
case HS_EX_TYPE_SERVER_NAME: return HS_EX_TYPE_ID_SERVER_NAME;
case HS_EX_TYPE_SUPPORTED_GROUPS: return HS_EX_TYPE_ID_SUPPORTED_GROUPS;
case HS_EX_TYPE_POINT_FORMATS: return HS_EX_TYPE_ID_POINT_FORMATS;
case HS_EX_TYPE_SIGNATURE_ALGORITHMS: return HS_EX_TYPE_ID_SIGNATURE_ALGORITHMS;
case HS_EX_TYPE_APP_LAYER_PROTOCOLS: return HS_EX_TYPE_ID_APP_LAYER_PROTOCOLS;
case HS_EX_TYPE_ENCRYPT_THEN_MAC: return HS_EX_TYPE_ID_ENCRYPT_THEN_MAC;
case HS_EX_TYPE_EXTENDED_MASTER_SECRET: return HS_EX_TYPE_ID_EXTENDED_MASTER_SECRET;
case HS_EX_TYPE_RECORD_SIZE_LIMIT: return HS_EX_TYPE_ID_RECORD_SIZE_LIMIT;
case HS_EX_TYPE_SESSION_TICKET: return HS_EX_TYPE_ID_SESSION_TICKET;
case HS_EX_TYPE_PRE_SHARED_KEY: return HS_EX_TYPE_ID_PRE_SHARED_KEY;
case HS_EX_TYPE_SUPPORTED_VERSIONS: return HS_EX_TYPE_ID_SUPPORTED_VERSIONS;
case HS_EX_TYPE_COOKIE: return HS_EX_TYPE_ID_COOKIE;
case HS_EX_TYPE_PSK_KEY_EXCHANGE_MODES: return HS_EX_TYPE_ID_PSK_KEY_EXCHANGE_MODES;
case HS_EX_TYPE_CERTIFICATE_AUTHORITIES: return HS_EX_TYPE_ID_CERTIFICATE_AUTHORITIES;
case HS_EX_TYPE_POST_HS_AUTH: return HS_EX_TYPE_ID_POST_HS_AUTH;
case HS_EX_TYPE_KEY_SHARE: return HS_EX_TYPE_ID_KEY_SHARE;
case HS_EX_TYPE_RENEGOTIATION_INFO: return HS_EX_TYPE_ID_RENEGOTIATION_INFO;
default: break;
}
return HS_EX_TYPE_ID_UNRECOGNIZED;
}
int32_t HS_CheckReceivedExtension(HITLS_Ctx *ctx, HS_MsgType hsType, uint64_t hsMsgExtensionsMask,
uint64_t hsMsgAllowedExtensionsMask)
{
#ifndef HITLS_BSL_LOG
(void)hsType;
#endif
if ((hsMsgExtensionsMask & hsMsgAllowedExtensionsMask) != hsMsgExtensionsMask) {
BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17311, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"%d msg have illegal extensions, extensionMask: %lu", hsType, hsMsgExtensionsMask, 0, 0);
ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_ILLEGAL_PARAMETER);
return HITLS_MSG_HANDLE_UNSUPPORT_EXTENSION_TYPE;
}
return HITLS_SUCCESS;
}
bool IsCipherSuiteAllowed(const HITLS_Ctx *ctx, uint16_t cipherSuite, bool checkNegoVersion)
{
if (!CFG_CheckCipherSuiteSupported(cipherSuite)) {
return false;
}
uint16_t minVersion = ctx->config.tlsConfig.minVersion;
uint16_t maxVersion = ctx->config.tlsConfig.maxVersion;
if (!CFG_CheckCipherSuiteVersion(cipherSuite, minVersion, maxVersion)) {
return false;
}
CipherSuiteInfo cipherInfo = {0};
(void)CFG_GetCipherSuiteInfo(cipherSuite, &cipherInfo);
if ((ctx->isClient && ctx->config.tlsConfig.pskClientCb == NULL) ||
(!ctx->isClient && ctx->config.tlsConfig.pskServerCb == NULL)) {
if ((cipherInfo.kxAlg == HITLS_KEY_EXCH_PSK) ||
(cipherInfo.kxAlg == HITLS_KEY_EXCH_DHE_PSK) ||
(cipherInfo.kxAlg == HITLS_KEY_EXCH_ECDHE_PSK) ||
(cipherInfo.kxAlg == HITLS_KEY_EXCH_RSA_PSK)) {
return false;
}
}
if (checkNegoVersion) {
uint16_t negotiatedVersion = ctx->negotiatedInfo.version;
if (negotiatedVersion > 0) {
if (!CFG_CheckCipherSuiteVersion(cipherSuite, negotiatedVersion, negotiatedVersion)) {
return false;
}
}
}
return true;
}
uint32_t HS_GetCryptLength(const TLS_Ctx *ctx, int32_t cmd, int32_t param)
{
const TLS_GroupInfo *groupInfo = ConfigGetGroupInfo(&ctx->config.tlsConfig, (uint16_t)param);
if (groupInfo == NULL) {
return 0;
}
switch (cmd) {
case HITLS_CRYPT_INFO_CMD_GET_PUBLIC_KEY_LEN:
return groupInfo->pubkeyLen;
case HITLS_CRYPT_INFO_CMD_GET_CIPHERTEXT_LEN:
return groupInfo->ciphertextLen;
default:
return 0;
}
}
HITLS_CERT_KeyType HS_SignScheme2CertKeyType(const HITLS_Ctx *ctx, HITLS_SignHashAlgo signScheme)
{
const TLS_SigSchemeInfo *info = ConfigGetSignatureSchemeInfo(&ctx->config.tlsConfig, signScheme);
return info == NULL ? TLS_CERT_KEY_TYPE_UNKNOWN : info->keyType;
}