* 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 <stdbool.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include "bsl_sal.h"
#include "frame_tls.h"
#include "hitls_config.h"
#include "hitls_error.h"
#include "bsl_errno.h"
#include "bsl_uio.h"
#include "frame_io.h"
#include "simulate_io.h"
#include "uio_abstraction.h"
#include "tls.h"
#include "tls_config.h"
#include "hitls_type.h"
#include "hitls_func.h"
#include "hitls.h"
#include "pack.h"
#include "bsl_err.h"
#include "bsl_bytes.h"
#include "custom_extensions.h"
#include "frame_tls.h"
#include "alert.h"
#include "frame_link.h"
#include "parse_extensions.h"
#include "parse_msg.h"
#include "parser_frame_msg.h"
#include "conn_init.h"
#include "hs.h"
#include "recv_process.h"
#define CUSTOM_EXTENTIONS_TYPE_1 0x00001
#define CUSTOM_EXTENTIONS_TYPE_2 0x00002
#define CUSTOM_PARSE_EXT_TYPE_1 0x1234
#define CUSTOM_PARSE_EXT_TYPE_2 0x1235
#define BULK_EMPTY_CUSTOM_EXT_BASE 0xFE00
#define BULK_EMPTY_CUSTOM_EXT_COUNT 257
static bool g_clientHelloCbCalled = false;
static bool g_clientHelloGetExtsPresentOk = false;
static bool g_clientHelloGetCustomExtOk = false;
static void ResetClientHelloCbState(void)
{
g_clientHelloCbCalled = false;
g_clientHelloGetExtsPresentOk = false;
g_clientHelloGetCustomExtOk = false;
}
static int32_t BulkCustomExtClientHelloCb(HITLS_Ctx *ctx, int32_t *alert, void *arg)
{
(void)arg;
uint16_t *exts = NULL;
uint32_t extLen = 0;
*alert = ALERT_INTERNAL_ERROR;
g_clientHelloCbCalled = true;
if (HITLS_ClientHelloGetExtensionsPresent(ctx, &exts, &extLen) != HITLS_SUCCESS) {
return HITLS_CLIENT_HELLO_FAILED;
}
g_clientHelloGetExtsPresentOk = (exts != NULL && extLen != 0);
for (uint32_t i = 0; i < extLen; i++) {
if (exts[i] == BULK_EMPTY_CUSTOM_EXT_BASE) {
g_clientHelloGetCustomExtOk = true;
break;
}
}
BSL_SAL_FREE(exts);
return HITLS_CLIENT_HELLO_SUCCESS;
}
static bool AppendEmptyCustomExtensionsToClientHello(uint8_t *buf, uint32_t *len, uint32_t bufSize)
{
uint32_t appendLen = BULK_EMPTY_CUSTOM_EXT_COUNT * 4;
uint32_t offset = 9;
uint32_t recLen;
uint32_t hsLen;
uint32_t extLenPos;
uint32_t extLen;
uint32_t extEnd;
if (buf == NULL || len == NULL || *len < 9) {
return false;
}
recLen = BSL_ByteToUint16(&buf[3]);
hsLen = BSL_ByteToUint24(&buf[6]);
offset += 2 + 32;
offset += 1 + buf[offset];
offset += 2 + BSL_ByteToUint16(&buf[offset]);
offset += 1 + buf[offset];
extLenPos = offset;
extLen = BSL_ByteToUint16(&buf[extLenPos]);
extEnd = extLenPos + 2 + extLen;
if (extEnd != *len || *len + appendLen > bufSize || extLen + appendLen > UINT16_MAX) {
return false;
}
for (uint32_t i = 0; i < BULK_EMPTY_CUSTOM_EXT_COUNT; i++) {
uint16_t extType = (uint16_t)(BULK_EMPTY_CUSTOM_EXT_BASE + i);
BSL_Uint16ToByte(extType, &buf[extEnd + i * 4]);
BSL_Uint16ToByte(0, &buf[extEnd + i * 4 + 2]);
}
extLen += appendLen;
recLen += appendLen;
hsLen += appendLen;
*len += appendLen;
BSL_Uint16ToByte((uint16_t)extLen, &buf[extLenPos]);
BSL_Uint16ToByte((uint16_t)recLen, &buf[3]);
BSL_Uint24ToByte(hsLen, &buf[6]);
return true;
}
int SimpleAddCb(const struct TlsCtx *ctx, uint16_t extType, uint32_t context, uint8_t **out, uint32_t *outLen,
HITLS_CERT_X509 *cert, uint32_t certId, uint32_t *alert, void *addArg)
{
(void)ctx;
(void)extType;
(void)context;
(void)cert;
(void)certId;
(void)alert;
(void)addArg;
*out = malloc(sizeof(uint16_t));
if (*out == NULL) {
return -1;
}
uint32_t bufOffset = 0;
(*out)[bufOffset] = 0xAA;
bufOffset++;
*outLen = bufOffset;
return HITLS_ADD_CUSTOM_EXTENSION_RET_PACK;
}
void SimpleFreeCb(const struct TlsCtx *ctx, uint16_t extType, uint32_t context, uint8_t *out, void *addArg)
{
(void)ctx;
(void)extType;
(void)context;
(void)addArg;
BSL_SAL_Free(out);
}
int SimpleParseCb(const struct TlsCtx *ctx, uint16_t extType, uint32_t context, const uint8_t **in, uint32_t *inLen,
HITLS_CERT_X509 *cert, uint32_t certId, uint32_t *alert, void *parseArg)
{
(void)ctx;
(void)extType;
(void)context;
(void)cert;
(void)certId;
(void)alert;
(void)parseArg;
if (*inLen <= 0) {
return 0;
}
uint8_t *dumpedData = BSL_SAL_Dump(*in, *inLen);
if (dumpedData == NULL) {
return 1;
}
if (dumpedData[0] != 0xAA) {
BSL_SAL_Free(dumpedData);
return 1;
}
BSL_SAL_Free(dumpedData);
return 0;
}
* @test SDV_TLS_PACK_CUSTOM_EXTENSIONS_API_TC001
* @title Test the single extension packing function of the PackCustomExtensions interface
* @precon None
* @brief
* 1. Initialize the TLS context and configure a single custom extension (no callback). Expected result 1.
* 2. Call the PackCustomExtensions interface and verify the packing result. Expected result 2.
* @expect
* 1. Initialization successful.
* 2. Returns HITLS_SUCCESS, packing length is 0 (no data without callback).
@ */
void SDV_TLS_PACK_CUSTOM_EXTENSIONS_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uint8_t buf[1024] = {0};
uint32_t bufLen = sizeof(buf);
uint32_t len = 0;
uint16_t extType = CUSTOM_EXTENTIONS_TYPE_1;
uint32_t context = 1;
CustomExtMethods exts = {0};
CustomExtMethod meth = {0};
meth.extType = extType;
meth.context = context;
meth.addCb = NULL;
meth.freeCb = NULL;
exts.meths = &meth;
exts.methsCount = 1;
ctx->config.tlsConfig.customExts = &exts;
uint32_t bufOffset = 0;
uint8_t *buffAddr = &buf[0];
PackPacket pkt = {.buf = &buffAddr, .bufLen = &bufLen, .bufOffset = &bufOffset};
ASSERT_EQ(PackCustomExtensions(ctx, &pkt, context, NULL, 0), HITLS_SUCCESS);
ctx->config.tlsConfig.customExts = NULL;
ASSERT_EQ(len, 0);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_Free(ctx);
HITLS_CFG_FreeConfig(tlsConfig);
return;
}
* @test SDV_TLS_PARSE_CUSTOM_EXTENSIONS_API_TC001
* @title Test the single extension parsing function of the ParseCustomExtensions interface
* @precon None
* @brief
* 1. Initialize the TLS context and configure a single custom extension (no callback). Expected result 1.
* 2. Prepare a buffer containing a single extension and call the ParseCustomExtensions interface. Expected result 2.
* @expect
* 1. Initialization successful.
* 2. Returns HITLS_SUCCESS, buffer offset is updated correctly.
@ */
void SDV_TLS_PARSE_CUSTOM_EXTENSIONS_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uint8_t buf[1024] = {0xAA};
uint32_t bufOffset = 0;
uint16_t extType = CUSTOM_EXTENTIONS_TYPE_1;
uint32_t context = 1;
uint32_t extLen = 1;
CustomExtMethods exts = {0};
CustomExtMethod meth = {0};
meth.extType = extType;
meth.parseCb = NULL;
exts.meths = &meth;
exts.methsCount = 1;
ctx->config.tlsConfig.customExts = &exts;
int32_t ret = ParseCustomExtensions(ctx, buf + bufOffset, extType, extLen, context, NULL, 0);
ctx->config.tlsConfig.customExts = NULL;
ASSERT_EQ(ret, HITLS_SUCCESS);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_Free(ctx);
HITLS_CFG_FreeConfig(tlsConfig);
return;
}
* @test SDV_TLS_PACK_CUSTOM_EXTENSIONS_MULTIPLE_API_TC001
* @title Test the multiple extensions packing function of the PackCustomExtensions interface
* @precon None
* @brief
* 1. Initialize the TLS context and configure two custom extensions. Expected result 1.
* 2. Call the PackCustomExtensions interface and verify the packing result. Expected result 2.
* @expect
* 1. Initialization successful.
* 2. Returns HITLS_SUCCESS, packing length is 0 (no data without callbacks).
@ */
void SDV_TLS_PACK_CUSTOM_EXTENSIONS_MULTIPLE_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uint8_t buf[1024] = {0};
uint32_t bufLen = sizeof(buf);
uint32_t len = 0;
uint32_t context = 1;
uint32_t methsCount = 1;
CustomExtMethods exts = {0};
CustomExtMethod meths[2] = {{0}, {0}};
meths[0].extType = CUSTOM_EXTENTIONS_TYPE_1;
meths[0].context = context;
meths[0].addCb = NULL;
meths[0].freeCb = NULL;
meths[1].extType = CUSTOM_EXTENTIONS_TYPE_2;
meths[1].context = context;
meths[1].addCb = NULL;
meths[1].freeCb = NULL;
exts.meths = meths;
exts.methsCount = methsCount;
ctx->config.tlsConfig.customExts = &exts;
uint32_t bufOffset = 0;
uint8_t *buffAddr = &buf[0];
PackPacket pkt = {.buf = &buffAddr, .bufLen = &bufLen, .bufOffset = &bufOffset};
int32_t ret = PackCustomExtensions(ctx, &pkt, context, NULL, 0);
ctx->config.tlsConfig.customExts = NULL;
ASSERT_EQ(ret, HITLS_SUCCESS);
ASSERT_EQ(len, 0);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_Free(ctx);
HITLS_CFG_FreeConfig(tlsConfig);
return;
}
* @test SDV_TLS_PACK_CUSTOM_EXTENSIONS_EMPTY_API_TC001
* @title Test the behavior of the PackCustomExtensions interface when there are no extensions
* @precon None
* @brief
* 1. Initialize the TLS context without configuring any custom extensions. Expected result 1.
* 2. Call the PackCustomExtensions interface and verify the packing result. Expected result 2.
* @expect
* 1. Initialization successful.
* 2. Returns HITLS_SUCCESS, packing length is 0.
@ */
void SDV_TLS_PACK_CUSTOM_EXTENSIONS_EMPTY_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uint8_t buf[1024] = {0};
uint32_t bufLen = sizeof(buf);
uint32_t len = 0;
uint32_t context = 1;
ctx->config.tlsConfig.customExts = NULL;
uint32_t bufOffset = 0;
uint8_t *buffAddr = &buf[0];
PackPacket pkt = {.buf = &buffAddr, .bufLen = &bufLen, .bufOffset = &bufOffset};
int32_t ret = PackCustomExtensions(ctx, &pkt, context, NULL, 0);
ASSERT_EQ(ret, HITLS_SUCCESS);
ASSERT_EQ(len, 0);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_CFG_FreeConfig(tlsConfig);
HITLS_Free(ctx);
return;
}
* @test SDV_TLS_PACK_CUSTOM_EXTENSIONS_CALLBACK_API_TC001
* @title Test the PackCustomExtensions interface with callbacks
* @precon None
* @brief
* 1. Initialize the TLS context and configure a single custom extension with add_cb and free_cb. Expected result 1.
* 2. Call the PackCustomExtensions interface and verify the packing result. Expected result 2.
* @expect
* 1. Initialization successful.
* 2. Returns HITLS_SUCCESS, packing length is 3 (ext_type + data), buffer content is correct.
@ */
void SDV_TLS_PACK_CUSTOM_EXTENSIONS_CALLBACK_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uint8_t buf[1024] = {0};
uint32_t bufLen = sizeof(buf);
uint32_t len = 0;
uint16_t extType = CUSTOM_EXTENTIONS_TYPE_1;
uint32_t context = 1;
uint32_t dataLen = 1;
CustomExtMethods exts = {0};
CustomExtMethod meth = {0};
meth.extType = extType;
meth.context = context;
meth.addCb = SimpleAddCb;
meth.freeCb = SimpleFreeCb;
exts.meths = &meth;
exts.methsCount = 1;
ctx->config.tlsConfig.customExts = &exts;
uint32_t bufOffset = 0;
uint8_t *buffAddr = &buf[0];
PackPacket pkt = {.buf = &buffAddr, .bufLen = &bufLen, .bufOffset = &bufOffset};
int32_t ret = PackCustomExtensions(ctx, &pkt, context, NULL, 0);
ctx->config.tlsConfig.customExts = NULL;
ASSERT_EQ(ret, HITLS_SUCCESS);
len += bufOffset;
ASSERT_EQ(len, sizeof(uint16_t) + sizeof(uint16_t) + dataLen);
uint16_t packedType = BSL_ByteToUint16(buf);
ASSERT_EQ(packedType, extType);
uint16_t packedLen = BSL_ByteToUint16(&buf[sizeof(uint16_t)]);
ASSERT_EQ(packedLen, 1);
ASSERT_EQ(buf[len - 1], 0xAA);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_CFG_FreeConfig(tlsConfig);
HITLS_Free(ctx);
return;
}
* @test SDV_TLS_PARSE_CUSTOM_EXTENSIONS_CALLBACK_API_TC001
* @title Test the ParseCustomExtensions interface with parse_cb
* @precon None
* @brief
* 1. Initialize the TLS context and configure a single custom extension with parse_cb. Expected result 1.
* 2. Prepare a buffer containing a single extension and call the ParseCustomExtensions interface. Expected result 2.
* @expect
* 1. Initialization successful.
* 2. Returns HITLS_SUCCESS, buffer offset is updated correctly.
@ */
void SDV_TLS_PARSE_CUSTOM_EXTENSIONS_CALLBACK_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uint8_t buf[1024] = {0xAA};
uint32_t bufOffset = 0;
uint16_t extType = CUSTOM_EXTENTIONS_TYPE_1;
uint32_t context = 1;
uint32_t extLen = 1;
CustomExtMethods exts = {0};
CustomExtMethod meth = {0};
meth.extType = extType;
meth.context = context;
meth.parseCb = SimpleParseCb;
exts.meths = &meth;
exts.methsCount = 1;
ctx->config.tlsConfig.customExts = &exts;
int32_t ret = ParseCustomExtensions(ctx, buf + bufOffset, extType, extLen, context, NULL, 0);
ctx->config.tlsConfig.customExts = NULL;
ASSERT_EQ(ret, HITLS_SUCCESS);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_CFG_FreeConfig(tlsConfig);
HITLS_Free(ctx);
return;
}
* @test SDV_TLS_SSLCTX_ADD_CUSTOM_EXTENSION_API_TC002
* @title Test the custom extension addition functionality of the HITLS_AddCustomExtension function
* @precon None
* @brief
* 1. Initialize the TLS context and add a valid custom extension, verify if the addition is successful.
* Expected result 1.
* 2. Attempt to add a duplicate custom extension, verify if the function rejects the duplicate addition.
* Expected result 2.
* 3. Call the function with invalid parameters (add_cb is NULL, free_cb is not NULL), verify if the function correctly
* handles the error. Expected result 3.
* @expect
* 1. Returns HITLS_SUCCESS, the custom extension is correctly added to the context.
* 2. Returns 0, the number of extensions does not increase.
* 3. Returns 0, the number of extensions does not increase.
@ */
void SDV_HITLS_ADD_CUSTOM_EXTENSION_API_TC001(void)
{
FRAME_Init();
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
uint16_t extType = CUSTOM_EXTENTIONS_TYPE_1;
uint16_t invalidExtType = CUSTOM_EXTENTIONS_TYPE_2;
uint32_t context = 1;
HITLS_AddCustomExtCallback addCb = SimpleAddCb;
HITLS_FreeCustomExtCallback freeCb = SimpleFreeCb;
void *addArg = NULL;
HITLS_ParseCustomExtCallback parseCb = SimpleParseCb;
void *parseArg = NULL;
HITLS_CustomExtParams params = {
.extType = extType,
.context = context,
.addCb = addCb,
.freeCb = freeCb,
.addArg = addArg,
.parseCb = parseCb,
.parseArg = parseArg
};
uint32_t ret = HITLS_CFG_AddCustomExtension(tlsConfig, ¶ms);
ASSERT_EQ(ret, HITLS_SUCCESS);
ASSERT_EQ(tlsConfig->customExts->methsCount, 1);
CustomExtMethod *meth = &tlsConfig->customExts->meths[0];
ASSERT_EQ(meth->extType, extType);
ASSERT_EQ(meth->context, context);
ASSERT_EQ(meth->addCb, addCb);
ASSERT_EQ(meth->freeCb, freeCb);
ASSERT_EQ(meth->addArg, addArg);
ASSERT_EQ(meth->parseCb, parseCb);
ASSERT_EQ(meth->parseArg, parseArg);
HITLS_CustomExtParams duplicateParams = {
.extType = extType,
.context = context,
.addCb = addCb,
.freeCb = freeCb,
.addArg = addArg,
.parseCb = parseCb,
.parseArg = parseArg
};
ret = HITLS_CFG_AddCustomExtension(tlsConfig, &duplicateParams);
ASSERT_EQ(ret, HITLS_CONFIG_DUP_CUSTOM_EXT);
ASSERT_EQ(tlsConfig->customExts->methsCount, 1);
HITLS_CustomExtParams invalidParams = {
.extType = invalidExtType,
.context = context,
.addCb = NULL,
.freeCb = freeCb,
.addArg = addArg,
.parseCb = parseCb,
.parseArg = parseArg
};
ret = HITLS_CFG_AddCustomExtension(tlsConfig, &invalidParams);
ASSERT_EQ(ret, HITLS_INVALID_INPUT);
ASSERT_EQ(tlsConfig->customExts->methsCount, 1);
EXIT:
HITLS_CFG_FreeConfig(tlsConfig);
return;
}
* @test SDV_TLS_PARSE_CLIENT_HELLO_DUP_CUSTOM_EXTENSION_TC001
* @title Repeated custom extensions in ClientHello should be rejected
* @precon None
* @brief
* 1. Create a TLS1.3 context and register one custom extension for ClientHello parsing.
* 2. Build a ClientHello extension block with the same custom extension type repeated twice.
* 3. Parse the extension block and verify duplicate extension is rejected.
* @expect
* Returns HITLS_PARSE_DUPLICATE_EXTENDED_MSG.
@ */
void SDV_TLS_PARSE_CLIENT_HELLO_DUP_CUSTOM_EXTENSION_TC001(void)
{
FRAME_Init();
BSL_UIO *uio = NULL;
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
ClientHelloMsg msg = {0};
uint8_t buf[] = {
0x12, 0x34, 0x00, 0x01, 0xAA,
0x12, 0x34, 0x00, 0x01, 0xAA
};
HITLS_CustomExtParams params = {
.extType = CUSTOM_PARSE_EXT_TYPE_1,
.context = HITLS_EX_TYPE_CLIENT_HELLO,
.addCb = NULL,
.freeCb = NULL,
.addArg = NULL,
.parseCb = SimpleParseCb,
.parseArg = NULL
};
ASSERT_EQ(HITLS_CFG_AddCustomExtension(tlsConfig, ¶ms), HITLS_SUCCESS);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uio = BSL_UIO_New(BSL_UIO_TcpMethod());
HITLS_SetUio(ctx, uio);
CONN_Init(ctx);
ASSERT_EQ(ParseClientExtension(ctx, buf, sizeof(buf), &msg), HITLS_PARSE_DUPLICATE_EXTENDED_MSG);
EXIT:
BSL_UIO_Free(uio);
HITLS_Free(ctx);
HITLS_CFG_FreeConfig(tlsConfig);
return;
}
* @test SDV_TLS_PARSE_NST_DUP_CUSTOM_EXTENSION_TC001
* @title Repeated custom extensions in TLS1.3 NewSessionTicket should be rejected
* @precon None
* @brief
* 1. Create a TLS1.3 context and register one custom extension for NewSessionTicket parsing.
* 2. Build a NewSessionTicket with the same custom extension repeated twice.
* 3. Parse the message and verify duplicate extension is rejected.
* @expect
* Returns HITLS_PARSE_DUPLICATE_EXTENDED_MSG.
@ */
void SDV_TLS_PARSE_NST_DUP_CUSTOM_EXTENSION_TC001(void)
{
FRAME_Init();
BSL_UIO *uio = NULL;
HITLS_Config *tlsConfig = HITLS_CFG_NewTLS13Config();
ASSERT_NE(tlsConfig, NULL);
HS_Msg hsMsg = {0};
uint8_t buf[] = {
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01,
0x01, 0xAA,
0x00, 0x01, 0xBB,
0x00, 0x0A,
0x12, 0x35, 0x00, 0x01, 0xAA,
0x12, 0x35, 0x00, 0x01, 0xAA
};
HITLS_CustomExtParams params = {
.extType = CUSTOM_PARSE_EXT_TYPE_2,
.context = HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET,
.addCb = NULL,
.freeCb = NULL,
.addArg = NULL,
.parseCb = SimpleParseCb,
.parseArg = NULL
};
ASSERT_EQ(HITLS_CFG_AddCustomExtension(tlsConfig, ¶ms), HITLS_SUCCESS);
HITLS_Ctx *ctx = HITLS_New(tlsConfig);
ASSERT_NE(ctx, NULL);
uio = BSL_UIO_New(BSL_UIO_TcpMethod());
HITLS_SetUio(ctx, uio);
CONN_Init(ctx);
ctx->negotiatedInfo.version = HITLS_VERSION_TLS13;
ASSERT_EQ(ParseNewSessionTicket(ctx, buf, sizeof(buf), &hsMsg), HITLS_PARSE_DUPLICATE_EXTENDED_MSG);
EXIT:
BSL_UIO_Free(uio);
CleanNewSessionTicket(&hsMsg.body.newSessionTicket);
HITLS_Free(ctx);
HITLS_CFG_FreeConfig(tlsConfig);
return;
}
typedef struct {
uint32_t parsedContext[10];
uint32_t parsedContextCount;
uint32_t addedContext[10];
uint32_t addedContextCount;
uint32_t alertContext;
uint32_t alert;
bool addEmptyExt;
bool parseEmptyExt;
bool passExt;
} CustomExtensionArg;
int CustomExtensionAddCb(const struct TlsCtx *ctx, uint16_t extType, uint32_t context, uint8_t **out, uint32_t *outLen,
HITLS_CERT_X509 *cert, uint32_t certId, uint32_t *alert, void *addArg)
{
(void)ctx;
(void)extType;
(void)cert;
(void)certId;
(void)alert;
CustomExtensionArg *arg = (CustomExtensionArg *)addArg;
arg->addedContext[arg->addedContextCount++] = context;
if ((arg->alertContext & context) != 0) {
*alert = arg->alert;
return -1;
}
if (arg->passExt) {
*out = NULL;
*outLen = 0;
return HITLS_ADD_CUSTOM_EXTENSION_RET_PASS;
}
if (arg->addEmptyExt) {
*out = NULL;
*outLen = 0;
return HITLS_ADD_CUSTOM_EXTENSION_RET_PACK;
}
*out = malloc(1);
if (*out == NULL) {
return -1;
}
*outLen = 1;
(*out)[0] = 0xAA;
return HITLS_ADD_CUSTOM_EXTENSION_RET_PACK;
}
void CustomExtensionFreeCb(const struct TlsCtx *ctx, uint16_t extType, uint32_t context, uint8_t *out, void *addArg)
{
(void)ctx;
(void)extType;
(void)context;
(void)addArg;
BSL_SAL_Free(out);
}
int CustomExtensionParseCb(const struct TlsCtx *ctx, uint16_t extType, uint32_t context, const uint8_t **in, uint32_t *inLen,
HITLS_CERT_X509 *cert, uint32_t certId, uint32_t *alert, void *parseArg)
{
(void)ctx;
(void)extType;
(void)context;
(void)cert;
(void)certId;
(void)alert;
CustomExtensionArg *arg = (CustomExtensionArg *)parseArg;
arg->parsedContext[arg->parsedContextCount++] = context;
if ((arg->alertContext & context) != 0) {
*alert = arg->alert;
return -1;
}
if (arg->parseEmptyExt) {
if (*inLen > 0) {
return -1;
}
return 0;
}
if (arg->passExt) {
return -1;
}
if (*inLen != 1 || (*in)[0] != 0xAA) {
return -1;
}
return 0;
}
* @test SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC001
* @title Basic Functionality Test for Custom Extensions
*/
void SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC001(void)
{
FRAME_Init();
HITLS_Config *clientConfig = HITLS_CFG_NewTLS13Config();
HITLS_Config *serverConfig = HITLS_CFG_NewTLS13Config();
HITLS_CFG_SetClientVerifySupport(serverConfig, true);
CustomExtensionArg serverArg = {0};
CustomExtensionArg clientArg = {0};
HITLS_CustomExtParams params = {
.extType = CUSTOM_EXTENTIONS_TYPE_2,
.context = HITLS_EX_TYPE_CLIENT_HELLO | HITLS_EX_TYPE_TLS1_3_SERVER_HELLO | HITLS_EX_TYPE_ENCRYPTED_EXTENSIONS | HITLS_EX_TYPE_TLS1_3_CERTIFICATE | HITLS_EX_TYPE_TLS1_3_CERTIFICATE_REQUEST | HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET,
.addCb = CustomExtensionAddCb,
.freeCb = CustomExtensionFreeCb,
.addArg = &clientArg,
.parseCb = CustomExtensionParseCb,
.parseArg = &clientArg
};
HITLS_CFG_AddCustomExtension(clientConfig, ¶ms);
params.addArg = &serverArg;
params.parseArg = &serverArg;
HITLS_CFG_AddCustomExtension(serverConfig, ¶ms);
FRAME_LinkObj *client = FRAME_CreateLink(clientConfig, BSL_UIO_TCP);
FRAME_LinkObj *server = FRAME_CreateLink(serverConfig, BSL_UIO_TCP);
ASSERT_EQ(FRAME_CreateConnection(client, server, true, HS_STATE_BUTT), HITLS_SUCCESS);
ASSERT_EQ(clientArg.addedContextCount, 3);
ASSERT_EQ(clientArg.parsedContextCount, 7);
ASSERT_EQ(clientArg.addedContext[0], HITLS_EX_TYPE_CLIENT_HELLO);
ASSERT_EQ(clientArg.addedContext[1], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(clientArg.addedContext[2], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(clientArg.parsedContext[0], HITLS_EX_TYPE_TLS1_2_SERVER_HELLO | HITLS_EX_TYPE_TLS1_3_SERVER_HELLO | HITLS_EX_TYPE_HELLO_RETRY_REQUEST);
ASSERT_EQ(clientArg.parsedContext[1], HITLS_EX_TYPE_ENCRYPTED_EXTENSIONS);
ASSERT_EQ(clientArg.parsedContext[2], HITLS_EX_TYPE_TLS1_3_CERTIFICATE_REQUEST);
ASSERT_EQ(clientArg.parsedContext[3], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(clientArg.parsedContext[4], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(clientArg.parsedContext[5], HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET);
ASSERT_EQ(clientArg.parsedContext[6], HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET);
ASSERT_EQ(serverArg.addedContextCount, 7);
ASSERT_EQ(serverArg.parsedContextCount, 3);
ASSERT_EQ(serverArg.parsedContext[0], HITLS_EX_TYPE_CLIENT_HELLO);
ASSERT_EQ(serverArg.parsedContext[1], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(serverArg.parsedContext[2], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(serverArg.addedContext[0], HITLS_EX_TYPE_TLS1_3_SERVER_HELLO);
ASSERT_EQ(serverArg.addedContext[1], HITLS_EX_TYPE_ENCRYPTED_EXTENSIONS);
ASSERT_EQ(serverArg.addedContext[2], HITLS_EX_TYPE_TLS1_3_CERTIFICATE_REQUEST);
ASSERT_EQ(serverArg.addedContext[3], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(serverArg.addedContext[4], HITLS_EX_TYPE_TLS1_3_CERTIFICATE);
ASSERT_EQ(serverArg.addedContext[5], HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET);
ASSERT_EQ(serverArg.addedContext[5], HITLS_EX_TYPE_TLS1_3_NEW_SESSION_TICKET);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_CFG_FreeConfig(clientConfig);
HITLS_CFG_FreeConfig(serverConfig);
FRAME_FreeLink(client);
FRAME_FreeLink(server);
}
* @test SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC002
* @title Alert Scenario Test for Custom Extensions
*/
void SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC002()
{
FRAME_Init();
HITLS_Config *clientConfig = HITLS_CFG_NewTLS13Config();
HITLS_Config *serverConfig = HITLS_CFG_NewTLS13Config();
CustomExtensionArg serverArg = {0};
CustomExtensionArg clientArg = {0};
clientArg.alert = ALERT_ILLEGAL_PARAMETER;
clientArg.alertContext = HITLS_EX_TYPE_TLS1_3_SERVER_HELLO;
HITLS_CustomExtParams params = {
.extType = CUSTOM_EXTENTIONS_TYPE_2,
.context = HITLS_EX_TYPE_CLIENT_HELLO | HITLS_EX_TYPE_TLS1_3_SERVER_HELLO,
.addCb = CustomExtensionAddCb,
.freeCb = CustomExtensionFreeCb,
.addArg = &clientArg,
.parseCb = CustomExtensionParseCb,
.parseArg = &clientArg
};
HITLS_CFG_AddCustomExtension(clientConfig, ¶ms);
params.addArg = &serverArg;
params.parseArg = &serverArg;
HITLS_CFG_AddCustomExtension(serverConfig, ¶ms);
FRAME_LinkObj *client = FRAME_CreateLink(clientConfig, BSL_UIO_TCP);
FRAME_LinkObj *server = FRAME_CreateLink(serverConfig, BSL_UIO_TCP);
ASSERT_EQ(FRAME_CreateConnection(client, server, true, HS_STATE_BUTT), -1);
ALERT_Info info = {0};
ALERT_GetInfo(client->ssl, &info);
ASSERT_EQ(info.flag, ALERT_FLAG_SEND);
ASSERT_EQ(info.level, ALERT_LEVEL_FATAL);
ASSERT_EQ(info.description, ALERT_ILLEGAL_PARAMETER);
EXIT:
HITLS_CFG_FreeConfig(clientConfig);
HITLS_CFG_FreeConfig(serverConfig);
FRAME_FreeLink(client);
FRAME_FreeLink(server);
}
* @test SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC003
* @title Empty Extension Capability Test
*/
void SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC003()
{
FRAME_Init();
HITLS_Config *clientConfig = HITLS_CFG_NewTLS13Config();
HITLS_Config *serverConfig = HITLS_CFG_NewTLS13Config();
CustomExtensionArg serverArg = {0};
CustomExtensionArg clientArg = {0};
clientArg.addEmptyExt = true;
clientArg.parseEmptyExt = false;
serverArg.addEmptyExt = false;
serverArg.parseEmptyExt = true;
HITLS_CustomExtParams params = {
.extType = CUSTOM_EXTENTIONS_TYPE_2,
.context = HITLS_EX_TYPE_CLIENT_HELLO | HITLS_EX_TYPE_TLS1_3_SERVER_HELLO,
.addCb = CustomExtensionAddCb,
.freeCb = CustomExtensionFreeCb,
.addArg = &clientArg,
.parseCb = CustomExtensionParseCb,
.parseArg = &clientArg
};
HITLS_CFG_AddCustomExtension(clientConfig, ¶ms);
params.addArg = &serverArg;
params.parseArg = &serverArg;
HITLS_CFG_AddCustomExtension(serverConfig, ¶ms);
FRAME_LinkObj *client = FRAME_CreateLink(clientConfig, BSL_UIO_TCP);
FRAME_LinkObj *server = FRAME_CreateLink(serverConfig, BSL_UIO_TCP);
ASSERT_EQ(FRAME_CreateConnection(client, server, true, HS_STATE_BUTT), 0);
ASSERT_EQ(clientArg.addedContextCount, 1);
ASSERT_EQ(clientArg.parsedContextCount, 1);
ASSERT_EQ(clientArg.addedContext[0], HITLS_EX_TYPE_CLIENT_HELLO);
ASSERT_EQ(clientArg.parsedContext[0], HITLS_EX_TYPE_TLS1_2_SERVER_HELLO | HITLS_EX_TYPE_TLS1_3_SERVER_HELLO | HITLS_EX_TYPE_HELLO_RETRY_REQUEST);
ASSERT_EQ(serverArg.addedContextCount, 1);
ASSERT_EQ(serverArg.parsedContextCount, 1);
ASSERT_EQ(serverArg.addedContext[0], HITLS_EX_TYPE_TLS1_3_SERVER_HELLO);
ASSERT_EQ(serverArg.parsedContext[0], HITLS_EX_TYPE_CLIENT_HELLO);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_CFG_FreeConfig(clientConfig);
HITLS_CFG_FreeConfig(serverConfig);
FRAME_FreeLink(client);
FRAME_FreeLink(server);
}
* @test SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC004
* @title Pass Extension Capability Test
*/
void SDV_HITLS_CUSTOM_EXTENSION_FUNCTION_TC004()
{
FRAME_Init();
HITLS_Config *clientConfig = HITLS_CFG_NewTLS13Config();
HITLS_Config *serverConfig = HITLS_CFG_NewTLS13Config();
CustomExtensionArg serverArg = {0};
CustomExtensionArg clientArg = {0};
clientArg.passExt = true;
serverArg.passExt = true;
HITLS_CustomExtParams params = {
.extType = CUSTOM_EXTENTIONS_TYPE_2,
.context = HITLS_EX_TYPE_CLIENT_HELLO | HITLS_EX_TYPE_TLS1_3_SERVER_HELLO,
.addCb = CustomExtensionAddCb,
.freeCb = CustomExtensionFreeCb,
.addArg = &clientArg,
.parseCb = CustomExtensionParseCb,
.parseArg = &clientArg
};
HITLS_CFG_AddCustomExtension(clientConfig, ¶ms);
params.addArg = &serverArg;
params.parseArg = &serverArg;
HITLS_CFG_AddCustomExtension(serverConfig, ¶ms);
FRAME_LinkObj *client = FRAME_CreateLink(clientConfig, BSL_UIO_TCP);
FRAME_LinkObj *server = FRAME_CreateLink(serverConfig, BSL_UIO_TCP);
ASSERT_EQ(FRAME_CreateConnection(client, server, true, HS_STATE_BUTT), 0);
ASSERT_EQ(clientArg.addedContextCount, 1);
ASSERT_EQ(clientArg.parsedContextCount, 0);
ASSERT_EQ(serverArg.addedContextCount, 1);
ASSERT_EQ(serverArg.parsedContextCount, 0);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
HITLS_CFG_FreeConfig(clientConfig);
HITLS_CFG_FreeConfig(serverConfig);
FRAME_FreeLink(client);
FRAME_FreeLink(server);
}
* @test SDV_TLS12_CLIENT_HELLO_GET_EXTENSIONS_PRESENT_MASS_CUSTOM_EXT_TC001
* @title TLS1.2 server ClientHello callback gets extension list with 257 empty custom extensions
* @precon None
* @brief
* 1. Create TLS1.2 client and server frame links, and set the server clientHello callback.
* 2. Drive the handshake until the server is ready to receive ClientHello.
* 3. Append 257 empty custom extensions to the serialized ClientHello.
* 4. Let the server process ClientHello and verify the callback successfully calls HITLS_ClientHelloGetExtensionsPresent.
* @expect
* 1. The callback is invoked successfully.
* 2. HITLS_ClientHelloGetExtensionsPresent succeeds.
* 3. One appended empty custom extension can be retrieved successfully.
* 4. The TLS1.2 handshake succeeds.
@ */
void SDV_TLS12_CLIENT_HELLO_GET_EXTENSIONS_PRESENT_MASS_CUSTOM_EXT_TC001(void)
{
FRAME_LinkObj *client = NULL;
FRAME_LinkObj *server = NULL;
HITLS_Config *clientConfig = NULL;
HITLS_Config *serverConfig = NULL;
FrameUioUserData *ioUserData = NULL;
FRAME_Msg frameMsg = {0};
uint32_t parseLen = 0;
FRAME_Init();
ResetClientHelloCbState();
clientConfig = HITLS_CFG_NewTLS12Config();
serverConfig = HITLS_CFG_NewTLS12Config();
ASSERT_TRUE(clientConfig != NULL);
ASSERT_TRUE(serverConfig != NULL);
ASSERT_EQ(HITLS_CFG_SetClientHelloCb(serverConfig, BulkCustomExtClientHelloCb, NULL), HITLS_SUCCESS);
client = FRAME_CreateLink(clientConfig, BSL_UIO_TCP);
server = FRAME_CreateLink(serverConfig, BSL_UIO_TCP);
ASSERT_TRUE(client != NULL);
ASSERT_TRUE(server != NULL);
ASSERT_EQ(FRAME_CreateConnection(client, server, false, TRY_RECV_CLIENT_HELLO), HITLS_SUCCESS);
ASSERT_EQ(server->ssl->hsCtx->state, TRY_RECV_CLIENT_HELLO);
ioUserData = BSL_UIO_GetUserData(server->io);
ASSERT_TRUE(ioUserData != NULL);
ASSERT_TRUE(ioUserData->recMsg.len != 0);
ASSERT_TRUE(AppendEmptyCustomExtensionsToClientHello(ioUserData->recMsg.msg, &ioUserData->recMsg.len,
sizeof(ioUserData->recMsg.msg)) == true);
CONN_Deinit(server->ssl);
HS_Init(server->ssl);
ASSERT_EQ(ParserTotalRecord(server, &frameMsg, ioUserData->recMsg.msg, ioUserData->recMsg.len, &parseLen), HITLS_SUCCESS);
ASSERT_EQ(frameMsg.body.handshakeMsg.type, CLIENT_HELLO);
server->ssl->hsCtx->hsMsg = &frameMsg.body.handshakeMsg;
CONN_Init(server->ssl);
ASSERT_EQ(ServerRecvClientHelloProcess(server->ssl, &frameMsg.body.handshakeMsg, true), HITLS_SUCCESS);
ASSERT_TRUE(g_clientHelloCbCalled);
ASSERT_TRUE(g_clientHelloGetExtsPresentOk);
ASSERT_TRUE(g_clientHelloGetCustomExtOk);
ASSERT_TRUE(TestIsErrStackEmpty());
EXIT:
if (server != NULL && server->ssl != NULL && server->ssl->hsCtx != NULL) {
server->ssl->hsCtx->hsMsg = NULL;
}
CleanRecordBody(&frameMsg);
HITLS_CFG_FreeConfig(clientConfig);
HITLS_CFG_FreeConfig(serverConfig);
FRAME_FreeLink(client);
FRAME_FreeLink(server);
ResetClientHelloCbState();
}