* 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 <stdint.h>
#include "hitls_build.h"
#include <string.h>
#include "bsl_err_internal.h"
#include "tls_binlog_id.h"
#include "bsl_log_internal.h"
#include "bsl_log.h"
#include "bsl_bytes.h"
#include "hitls_error.h"
#include "hs_msg.h"
#include "hs_ctx.h"
#include "hitls_cert_type.h"
#include "bsl_list.h"
#include "pack_common.h"
#ifdef HITLS_TLS_FEATURE_SECURITY
#include "security.h"
#endif
#define BUFFER_GROW_FACTOR 2u
#ifdef HITLS_TLS_PROTO_DTLS12
* @brief Pack the packet header.
*
* @param type [IN] message type
* @param sequence [IN] Sequence number (dedicated for DTLS)
* @param length [IN] message body length
* @param buf [OUT] message header
*/
void PackDtlsMsgHeader(HS_MsgType type, uint16_t sequence, uint32_t length, uint8_t *buf)
{
buf[0] = (uint8_t)type & 0xffu;
BSL_Uint24ToByte(length, &buf[DTLS_HS_MSGLEN_ADDR]);
BSL_Uint16ToByte(
sequence, &buf[DTLS_HS_MSGSEQ_ADDR]);
BSL_Uint24ToByte(
0, &buf[DTLS_HS_FRAGMENT_OFFSET_ADDR]);
BSL_Uint24ToByte(
length, &buf[DTLS_HS_FRAGMENT_LEN_ADDR]);
}
#endif
#if defined(HITLS_TLS_FEATURE_SESSION_ID) || defined(HITLS_TLS_PROTO_TLS13)
* @brief Pack the message session ID.
*
* @param id [IN] Session ID
* @param idSize [IN] Session ID length
* @param buf [OUT] message buffer
* @param bufLen [IN] Maximum message length
* @param usedLen [OUT] Length of the packed message
*
* @retval HITLS_SUCCESS Assembly succeeded.
* @retval HITLS_PACK_SESSIONID_ERR Failed to pack the sessionId.
* @retval HITLS_MEMCPY_FAIL Memory Copy Failure
*/
int32_t PackSessionId(PackPacket *pkt, const uint8_t *id, uint32_t idSize)
{
if ((idSize != 0) && ((idSize > TLS_HS_MAX_SESSION_ID_SIZE) || (idSize < TLS_HS_MIN_SESSION_ID_SIZE))) {
BSL_ERR_PUSH_ERROR(HITLS_PACK_SESSIONID_ERR);
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15849, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"session id size is incorrect when pace session id.", 0, 0, 0, 0);
return HITLS_PACK_SESSIONID_ERR;
}
int32_t ret = PackAppendUint8ToBuf(pkt, (uint8_t)idSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (idSize == 0u) {
return HITLS_SUCCESS;
}
return PackAppendDataToBuf(pkt, id, idSize);
}
#endif
#ifdef HITLS_TLS_FEATURE_CERTIFICATE_AUTHORITIES
int32_t PackTrustedCAList(HITLS_TrustedCAList *caList, PackPacket *pkt)
{
if (caList == NULL) {
return HITLS_NULL_INPUT;
}
int32_t ret = HITLS_SUCCESS;
for (BslListNode *caNode = BSL_LIST_FirstNode(caList); caNode != NULL;
caNode = BSL_LIST_GetNextNode(caList, caNode)) {
HITLS_TrustedCANode *node = (HITLS_TrustedCANode *)BSL_LIST_GetData(caNode);
if (node->data != NULL && node->dataSize != 0) {
ret = PackAppendUint16ToBuf(pkt, (uint16_t)node->dataSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = PackAppendDataToBuf(pkt, node->data, node->dataSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
}
return HITLS_SUCCESS;
}
#endif
#ifdef HITLS_TLS_PROTO_TLS13
int32_t PackCertificateReqCtx(const TLS_Ctx *ctx, PackPacket *pkt)
{
int32_t ret = PackAppendUint8ToBuf(pkt, (uint8_t)ctx->certificateReqCtxSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (ctx->certificateReqCtxSize > 0) {
ret = PackAppendDataToBuf(pkt, ctx->certificateReqCtx, ctx->certificateReqCtxSize);
if (ret != HITLS_SUCCESS) {
return ret;
}
}
return HITLS_SUCCESS;
}
#endif
int32_t PackHelloCommonField(const TLS_Ctx *ctx, PackPacket *pkt, uint16_t version, bool isClient)
{
int32_t ret = HITLS_SUCCESS;
#ifdef HITLS_TLS_FEATURE_SECURITY
ret = SECURITY_CfgCheck(&ctx->config.tlsConfig, HITLS_SECURITY_SECOP_VERSION, 0, version, NULL);
if (ret != SECURITY_SUCCESS) {
BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16924, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
"CfgCheck fail, ret %d", ret, 0, 0, 0);
ctx->method.sendAlert((TLS_Ctx *)(uintptr_t)ctx, ALERT_LEVEL_FATAL, ALERT_INSUFFICIENT_SECURITY);
BSL_ERR_PUSH_ERROR(HITLS_PACK_UNSECURE_VERSION);
return HITLS_PACK_UNSECURE_VERSION;
}
#endif
ret = PackAppendUint16ToBuf(pkt, version);
if (ret != HITLS_SUCCESS) {
return ret;
}
ret = PackAppendDataToBuf(pkt, isClient ? ctx->hsCtx->clientRandom : ctx->hsCtx->serverRandom, HS_RANDOM_SIZE);
if (ret != HITLS_SUCCESS) {
return ret;
}
#if defined(HITLS_TLS_FEATURE_SESSION_ID) || defined(HITLS_TLS_PROTO_TLS13)
HS_Ctx *hsCtx = (HS_Ctx *)ctx->hsCtx;
ret = PackSessionId(pkt, hsCtx->sessionId, hsCtx->sessionIdSize);
if (ret != HITLS_SUCCESS) {
memset(hsCtx->sessionId, 0, hsCtx->sessionIdSize);
return ret;
}
#else
ret = PackAppendUint8ToBuf(pkt, 0);
if (ret != HITLS_SUCCESS) {
return ret;
}
#endif
return HITLS_SUCCESS;
}
static int32_t PackMsBufferGrow(PackPacket *pkt, uint32_t newSize)
{
uint32_t oldDataSize = *pkt->bufLen;
uint8_t *newAddr = BSL_SAL_Realloc(*pkt->buf, newSize, oldDataSize);
if (newAddr == NULL) {
return HITLS_MEMALLOC_FAIL;
}
*pkt->buf = newAddr;
*pkt->bufLen = newSize;
return HITLS_SUCCESS;
}
static int32_t PackMsBufferPrepare(PackPacket *pkt, uint32_t msgSize)
{
if (*pkt->bufLen - *pkt->bufOffset >= msgSize) {
return HITLS_SUCCESS;
}
if (HITLS_HS_BUFFER_SIZE_LIMIT - *pkt->bufOffset < msgSize) {
return HITLS_PACK_NOT_ENOUGH_BUF_LENGTH;
}
uint32_t oldBufSize = *pkt->bufLen;
uint32_t newBufSize = (msgSize > oldBufSize) ? msgSize : oldBufSize;
if (newBufSize >= HITLS_HS_BUFFER_SIZE_LIMIT / BUFFER_GROW_FACTOR) {
newBufSize = HITLS_HS_BUFFER_SIZE_LIMIT;
} else {
newBufSize = newBufSize * BUFFER_GROW_FACTOR;
}
return PackMsBufferGrow(pkt, newBufSize);
}
int32_t PackAppendUint8ToBuf(PackPacket *pkt, uint8_t value)
{
int32_t ret = PackMsBufferPrepare(pkt, sizeof(uint8_t));
if (ret != HITLS_SUCCESS) {
return ret;
}
(*pkt->buf)[*pkt->bufOffset] = value;
*pkt->bufOffset += sizeof(uint8_t);
return HITLS_SUCCESS;
}
int32_t PackAppendUint16ToBuf(PackPacket *pkt, uint16_t value)
{
int32_t ret = PackMsBufferPrepare(pkt, sizeof(uint16_t));
if (ret != HITLS_SUCCESS) {
return ret;
}
BSL_Uint16ToByte(value, &(*pkt->buf)[*pkt->bufOffset]);
*pkt->bufOffset += sizeof(uint16_t);
return HITLS_SUCCESS;
}
int32_t PackAppendUint24ToBuf(PackPacket *pkt, uint32_t value)
{
int32_t ret = PackMsBufferPrepare(pkt, UINT24_SIZE);
if (ret != HITLS_SUCCESS) {
return ret;
}
BSL_Uint24ToByte(value, &(*pkt->buf)[*pkt->bufOffset]);
*pkt->bufOffset += UINT24_SIZE;
return HITLS_SUCCESS;
}
int32_t PackAppendUint32ToBuf(PackPacket *pkt, uint32_t value)
{
int32_t ret = PackMsBufferPrepare(pkt, sizeof(uint32_t));
if (ret != HITLS_SUCCESS) {
return ret;
}
BSL_Uint32ToByte(value, &(*pkt->buf)[*pkt->bufOffset]);
*pkt->bufOffset += sizeof(uint32_t);
return HITLS_SUCCESS;
}
int32_t PackAppendUint64ToBuf(PackPacket *pkt, uint64_t value)
{
int32_t ret = PackMsBufferPrepare(pkt, sizeof(uint64_t));
if (ret != HITLS_SUCCESS) {
return ret;
}
BSL_Uint64ToByte(value, &(*pkt->buf)[*pkt->bufOffset]);
*pkt->bufOffset += sizeof(uint64_t);
return HITLS_SUCCESS;
}
int32_t PackAppendDataToBuf(PackPacket *pkt, const uint8_t *data, uint32_t size)
{
int32_t ret = PackMsBufferPrepare(pkt, size);
if (ret != HITLS_SUCCESS) {
return ret;
}
memcpy(&(*pkt->buf)[*pkt->bufOffset], data, size);
*pkt->bufOffset += size;
return HITLS_SUCCESS;
}
int32_t PackReserveBytes(PackPacket *pkt, uint32_t size, uint8_t **reservedBuf)
{
int32_t ret = PackMsBufferPrepare(pkt, size);
if (ret != HITLS_SUCCESS) {
return ret;
}
if (reservedBuf != NULL) {
*reservedBuf = &(*pkt->buf)[*pkt->bufOffset];
}
return HITLS_SUCCESS;
}
int32_t PackStartLengthField(PackPacket *pkt, uint32_t size, uint32_t *allocatedPosition)
{
int32_t ret = PackMsBufferPrepare(pkt, size);
if (ret != HITLS_SUCCESS) {
return ret;
}
*allocatedPosition = *pkt->bufOffset;
*pkt->bufOffset += size;
return HITLS_SUCCESS;
}
int32_t PackSkipBytes(PackPacket *pkt, uint32_t size)
{
if (*pkt->bufLen - *pkt->bufOffset < size) {
return HITLS_PACK_NOT_ENOUGH_BUF_LENGTH;
}
*pkt->bufOffset += size;
return HITLS_SUCCESS;
}
void PackCloseUint8Field(const PackPacket *pkt, uint32_t position)
{
(*pkt->buf)[position] = (uint8_t)(*pkt->bufOffset - position - sizeof(uint8_t));
}
void PackCloseUint16Field(const PackPacket *pkt, uint32_t position)
{
BSL_Uint16ToByte((uint16_t)(*pkt->bufOffset - position - sizeof(uint16_t)), &(*pkt->buf)[position]);
}
void PackCloseUint24Field(const PackPacket *pkt, uint32_t position)
{
BSL_Uint24ToByte((uint32_t)(*pkt->bufOffset - position - UINT24_SIZE), &(*pkt->buf)[position]);
}
int32_t PackGetSubBuffer(const PackPacket *pkt, uint32_t start, uint32_t *length, uint8_t **buf)
{
if (length == NULL) {
return HITLS_NULL_INPUT;
}
if (start > *pkt->bufOffset) {
return HITLS_PACK_NOT_ENOUGH_BUF_LENGTH;
}
*length = *pkt->bufOffset - start;
if (buf != NULL) {
*buf = &(*pkt->buf)[start];
}
return HITLS_SUCCESS;
}