Merge pull request #7951 from julek-wolfssl/dtls13-cid-fixes

DTLS 1.3 CID fixes
pull/7992/head
JacobBarthelmeh 2024-09-18 09:38:15 -06:00 committed by GitHub
commit fb2144d290
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 491 additions and 271 deletions

View File

@ -1209,6 +1209,11 @@ int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output,
return 0;
}
int Dtls13MinimumRecordLength(WOLFSSL* ssl)
{
return Dtls13GetRlHeaderLength(ssl, 1) + DTLS13_MIN_CIPHERTEXT;
}
/**
* Dtls13EncryptRecordNumber() - encrypt record number in the header
* @ssl: ssl object
@ -1225,9 +1230,15 @@ int Dtls13EncryptRecordNumber(WOLFSSL* ssl, byte* hdr, word16 recordLength)
if (ssl == NULL || hdr == NULL)
return BAD_FUNC_ARG;
#ifdef HAVE_NULL_CIPHER
/* Do not encrypt record numbers with null cipher. See RFC 9150 Sec 9 */
if (ssl->specs.bulk_cipher_algorithm == wolfssl_cipher_null)
return 0;
#endif /*HAVE_NULL_CIPHER */
/* we need at least a 16 bytes of ciphertext to encrypt record number see
4.2.3*/
if (recordLength < Dtls13GetRlHeaderLength(ssl, 1) + DTLS13_MIN_CIPHERTEXT)
if (recordLength < Dtls13MinimumRecordLength(ssl))
return BUFFER_ERROR;
seqLength = (*hdr & DTLS13_LEN_BIT) ? DTLS13_SEQ_16_LEN : DTLS13_SEQ_8_LEN;
@ -1453,17 +1464,22 @@ int Dtls13ParseUnifiedRecordLayer(WOLFSSL* ssl, const byte* input,
hdrInfo->recordLength = inputSize - idx;
}
/* minimum size for a dtls1.3 packet is 16 bytes (to have enough ciphertext
to create record number xor mask). (draft 43 - Sec 4.2.3) */
if (hdrInfo->recordLength < DTLS13_RN_MASK_SIZE)
return LENGTH_ERROR;
if (inputSize < idx + DTLS13_RN_MASK_SIZE)
return BUFFER_ERROR;
/* Do not encrypt record numbers with null cipher. See RFC 9150 Sec 9 */
if (ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null)
{
/* minimum size for a dtls1.3 packet is 16 bytes (to have enough
* ciphertext to create record number xor mask).
* (draft 43 - Sec 4.2.3) */
if (hdrInfo->recordLength < DTLS13_RN_MASK_SIZE)
return LENGTH_ERROR;
if (inputSize < idx + DTLS13_RN_MASK_SIZE)
return BUFFER_ERROR;
ret = Dtls13EncryptDecryptRecordNumber(ssl, seqNum, seqLen, input + idx,
DEPROTECT);
if (ret != 0)
return ret;
ret = Dtls13EncryptDecryptRecordNumber(ssl, seqNum, seqLen, input + idx,
DEPROTECT);
if (ret != 0)
return ret;
}
if (seqLen == DTLS13_SEQ_16_LEN) {
hdrInfo->seqHiPresent = 1;

View File

@ -11255,6 +11255,11 @@ static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx,
if (ret != 0)
return ret;
if (ssl->dtls13CurRlLength > sizeof(ssl->dtls13CurRL)) {
WOLFSSL_MSG("Record header too long");
return SEQUENCE_ERROR;
}
if (readSize < ssl->dtls13CurRlLength + DTLS13_RN_MASK_SIZE) {
/* when using DTLS over a medium that does not guarantee that a full
* message is received in a single read, we may end up without the full
@ -24789,6 +24794,14 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
if (IsEncryptionOn(ssl, 1) || ssl->options.tls1_3)
outputSz += cipherExtraData(ssl);
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
if (ssl->options.dtls) {
unsigned int cidSz = 0;
if (wolfSSL_dtls_cid_get_tx_size(ssl, &cidSz) == WOLFSSL_SUCCESS)
outputSz += cidSz;
}
#endif
/* check for available size */
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
return ssl->error = ret;
@ -25935,7 +25948,7 @@ void SetErrorString(int error, char* str)
*/
#ifndef NO_ERROR_STRINGS
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
#define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NONE}
#define SUITE_ALIAS(x,z,w,v,u) {(x),"",(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS},
@ -25944,7 +25957,7 @@ void SetErrorString(int error, char* str)
#define SUITE_ALIAS(x,z,w,v,u) {(x),"",(z),(w),WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS},
#endif
#else
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
#define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NONE}
#define SUITE_ALIAS(x,z,w,v,u) {(x),(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS},
@ -26806,13 +26819,16 @@ const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
}
int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
byte* cipherSuite, int* flags)
byte* cipherSuite, byte* major, byte* minor, int* flags)
{
int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
int i;
unsigned long len;
const char* nameDelim;
(void)major;
(void)minor;
/* Support trailing : */
nameDelim = XSTRSTR(name, ":");
if (nameDelim)
@ -26830,9 +26846,19 @@ int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
#endif
if (found) {
*cipherSuite0 = cipher_names[i].cipherSuite0;
*cipherSuite = cipher_names[i].cipherSuite;
*flags = cipher_names[i].flags;
if (cipherSuite0 != NULL)
*cipherSuite0 = cipher_names[i].cipherSuite0;
if (cipherSuite != NULL)
*cipherSuite = cipher_names[i].cipherSuite;
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
if (major != NULL)
*major = cipher_names[i].major;
if (minor != NULL)
*minor = cipher_names[i].minor;
#endif
if (flags != NULL)
*flags = cipher_names[i].flags;
ret = 0;
break;
}

View File

@ -8412,6 +8412,8 @@ static int CheckcipherList(const char* list)
char name[MAX_SUITE_NAME + 1];
word32 length = MAX_SUITE_NAME;
word32 current_length;
byte major = INVALID_BYTE;
byte minor = INVALID_BYTE;
next = XSTRSTR(next, ":");
@ -8436,10 +8438,10 @@ static int CheckcipherList(const char* list)
break;
}
ret = wolfSSL_get_cipher_suite_from_name(name, &cipherSuite0,
&cipherSuite1, &flags);
ret = GetCipherSuiteFromName(name, &cipherSuite0,
&cipherSuite1, &major, &minor, &flags);
if (ret == 0) {
if (cipherSuite0 == TLS13_BYTE) {
if (cipherSuite0 == TLS13_BYTE || minor == TLSv1_3_MINOR) {
/* TLSv13 suite */
findTLSv13Suites = 1;
}
@ -14297,7 +14299,8 @@ int wolfSSL_get_cipher_suite_from_name(const char* name, byte* cipherSuite0,
(cipherSuite == NULL) ||
(flags == NULL))
return BAD_FUNC_ARG;
return GetCipherSuiteFromName(name, cipherSuite0, cipherSuite, flags);
return GetCipherSuiteFromName(name, cipherSuite0, cipherSuite, NULL, NULL,
flags);
}

View File

@ -13500,7 +13500,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
ssl->arrays->client_identity, MAX_PSK_ID_LEN,
ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName);
if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
&cipherSuite, &cipherSuiteFlags) != 0) {
&cipherSuite, NULL, NULL, &cipherSuiteFlags) != 0) {
return PSK_KEY_ERROR;
}
}

View File

@ -3199,6 +3199,7 @@ typedef struct BuildMsg13Args {
word32 idx;
word32 headerSz;
word16 size;
word32 paddingSz;
} BuildMsg13Args;
static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs)
@ -3304,7 +3305,14 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
args->sz++;
/* Authentication data at the end. */
args->sz += ssl->specs.aead_mac_size;
#ifdef WOLFSSL_DTLS13
/* Pad to minimum length */
if (ssl->options.dtls &&
args->sz < (word32)Dtls13MinimumRecordLength(ssl)) {
args->paddingSz = Dtls13MinimumRecordLength(ssl) - args->sz;
args->sz = Dtls13MinimumRecordLength(ssl);
}
#endif
if (sizeOnly)
return (int)args->sz;
@ -3348,6 +3356,9 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
/* The real record content type goes at the end of the data. */
output[args->idx++] = (byte)type;
/* Double check that any necessary padding is zero'd out */
XMEMSET(output + args->idx, 0, args->paddingSz);
args->idx += args->paddingSz;
ssl->options.buildMsgState = BUILD_MSG_ENCRYPT;
}
@ -3393,7 +3404,8 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
#ifdef WOLFSSL_DTLS13
if (ret == 0 && ssl->options.dtls) {
/* AAD points to the header. Reuse the variable */
ret = Dtls13EncryptRecordNumber(ssl, (byte*)aad, (word16)args->sz);
ret = Dtls13EncryptRecordNumber(ssl, (byte*)aad,
(word16)args->sz);
}
#endif /* WOLFSSL_DTLS13 */
}
@ -3940,7 +3952,7 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello)
MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN,
&cipherName);
if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
&cipherSuite, &cipherSuiteFlags) != 0) {
&cipherSuite, NULL, NULL, &cipherSuiteFlags) != 0) {
WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
return PSK_KEY_ERROR;
}
@ -5852,7 +5864,7 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key,
if (*psk_keySz != 0) {
int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE;
*found = (GetCipherSuiteFromName(cipherName, &cipherSuite0,
&cipherSuite, &cipherSuiteFlags) == 0);
&cipherSuite, NULL, NULL, &cipherSuiteFlags) == 0);
(void)cipherSuiteFlags;
}
}

View File

@ -599,6 +599,248 @@ static int testDevId = WOLFSSL_CAAM_DEVID;
static int testDevId = INVALID_DEVID;
#endif
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \
!defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT)
/* This set of memio functions allows for more fine tuned control of the TLS
* connection operations. For new tests, try to use ssl_memio first. */
/* To dump the memory in gdb use
* dump memory client.bin test_ctx.c_buff test_ctx.c_buff+test_ctx.c_len
* dump memory server.bin test_ctx.s_buff test_ctx.s_buff+test_ctx.s_len
* This can be imported into Wireshark by transforming the file with
* od -Ax -tx1 -v client.bin > client.bin.hex
* od -Ax -tx1 -v server.bin > server.bin.hex
* And then loading test_output.dump.hex into Wireshark using the
* "Import from Hex Dump..." option ion and selecting the TCP
* encapsulation option.
*/
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES
static WC_INLINE int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz,
void *ctx)
{
struct test_memio_ctx *test_ctx;
byte *buf;
int *len;
test_ctx = (struct test_memio_ctx*)ctx;
if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
buf = test_ctx->c_buff;
len = &test_ctx->c_len;
}
else {
buf = test_ctx->s_buff;
len = &test_ctx->s_len;
}
if ((unsigned)(*len + sz) > TEST_MEMIO_BUF_SZ)
return WOLFSSL_CBIO_ERR_WANT_WRITE;
#ifdef WOLFSSL_DUMP_MEMIO_STREAM
{
char dump_file_name[64];
WOLFSSL_BIO *dump_file;
sprintf(dump_file_name, "%s/%s.dump", tmpDirName, currentTestName);
dump_file = wolfSSL_BIO_new_file(dump_file_name, "a");
if (dump_file != NULL) {
(void)wolfSSL_BIO_write(dump_file, data, sz);
wolfSSL_BIO_free(dump_file);
}
}
#endif
XMEMCPY(buf + *len, data, (size_t)sz);
*len += sz;
return sz;
}
static WC_INLINE int test_memio_read_cb(WOLFSSL *ssl, char *data, int sz,
void *ctx)
{
struct test_memio_ctx *test_ctx;
int read_sz;
byte *buf;
int *len;
test_ctx = (struct test_memio_ctx*)ctx;
if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
buf = test_ctx->s_buff;
len = &test_ctx->s_len;
}
else {
buf = test_ctx->c_buff;
len = &test_ctx->c_len;
}
if (*len == 0)
return WOLFSSL_CBIO_ERR_WANT_READ;
read_sz = sz < *len ? sz : *len;
XMEMCPY(data, buf, (size_t)read_sz);
XMEMMOVE(buf, buf + read_sz,(size_t) (*len - read_sz));
*len -= read_sz;
return read_sz;
}
int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
int max_rounds, int *rounds)
{
byte handshake_complete = 0, hs_c = 0, hs_s = 0;
int ret, err;
if (rounds != NULL)
*rounds = 0;
while (!handshake_complete && max_rounds > 0) {
if (!hs_c) {
wolfSSL_SetLoggingPrefix("client");
ret = wolfSSL_connect(ssl_c);
wolfSSL_SetLoggingPrefix(NULL);
if (ret == WOLFSSL_SUCCESS) {
hs_c = 1;
}
else {
err = wolfSSL_get_error(ssl_c, ret);
if (err != WOLFSSL_ERROR_WANT_READ &&
err != WOLFSSL_ERROR_WANT_WRITE)
return -1;
}
}
if (!hs_s) {
wolfSSL_SetLoggingPrefix("server");
ret = wolfSSL_accept(ssl_s);
wolfSSL_SetLoggingPrefix(NULL);
if (ret == WOLFSSL_SUCCESS) {
hs_s = 1;
}
else {
err = wolfSSL_get_error(ssl_s, ret);
if (err != WOLFSSL_ERROR_WANT_READ &&
err != WOLFSSL_ERROR_WANT_WRITE)
return -1;
}
}
handshake_complete = hs_c && hs_s;
max_rounds--;
if (rounds != NULL)
*rounds = *rounds + 1;
}
if (!handshake_complete)
return -1;
return 0;
}
int test_memio_setup_ex(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s,
byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
byte *serverKey, int serverKeySz)
{
int ret;
(void)caCert;
(void)caCertSz;
(void)serverCert;
(void)serverCertSz;
(void)serverKey;
(void)serverKeySz;
if (ctx_c != NULL && *ctx_c == NULL) {
*ctx_c = wolfSSL_CTX_new(method_c());
if (*ctx_c == NULL)
return -1;
#ifndef NO_CERTS
if (caCert == NULL) {
ret = wolfSSL_CTX_load_verify_locations(*ctx_c, caCertFile, 0);
}
else {
ret = wolfSSL_CTX_load_verify_buffer(*ctx_c, caCert, (long)caCertSz,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return -1;
#endif /* NO_CERTS */
wolfSSL_SetIORecv(*ctx_c, test_memio_read_cb);
wolfSSL_SetIOSend(*ctx_c, test_memio_write_cb);
if (ctx->c_ciphers != NULL) {
ret = wolfSSL_CTX_set_cipher_list(*ctx_c, ctx->c_ciphers);
if (ret != WOLFSSL_SUCCESS)
return -1;
}
}
if (ctx_s != NULL && *ctx_s == NULL) {
*ctx_s = wolfSSL_CTX_new(method_s());
if (*ctx_s == NULL)
return -1;
#ifndef NO_CERTS
if (serverKey == NULL) {
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx_s, svrKeyFile,
WOLFSSL_FILETYPE_PEM);
}
else {
ret = wolfSSL_CTX_use_PrivateKey_buffer(*ctx_s, serverKey,
(long)serverKeySz, WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return- -1;
if (serverCert == NULL) {
ret = wolfSSL_CTX_use_certificate_file(*ctx_s, svrCertFile,
WOLFSSL_FILETYPE_PEM);
}
else {
ret = wolfSSL_CTX_use_certificate_chain_buffer_format(*ctx_s,
serverCert, (long)serverCertSz, WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return -1;
#endif /* NO_CERTS */
wolfSSL_SetIORecv(*ctx_s, test_memio_read_cb);
wolfSSL_SetIOSend(*ctx_s, test_memio_write_cb);
if (ctx->s_ciphers != NULL) {
ret = wolfSSL_CTX_set_cipher_list(*ctx_s, ctx->s_ciphers);
if (ret != WOLFSSL_SUCCESS)
return -1;
}
}
if (ctx_c != NULL && ssl_c != NULL) {
*ssl_c = wolfSSL_new(*ctx_c);
if (*ssl_c == NULL)
return -1;
wolfSSL_SetIOWriteCtx(*ssl_c, ctx);
wolfSSL_SetIOReadCtx(*ssl_c, ctx);
}
if (ctx_s != NULL && ssl_s != NULL) {
*ssl_s = wolfSSL_new(*ctx_s);
if (*ssl_s == NULL)
return -1;
wolfSSL_SetIOWriteCtx(*ssl_s, ctx);
wolfSSL_SetIOReadCtx(*ssl_s, ctx);
#if !defined(NO_DH)
SetDH(*ssl_s);
#endif
}
return 0;
}
int test_memio_setup(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s)
{
return test_memio_setup_ex(ctx, ctx_c, ctx_s, ssl_c, ssl_s, method_c,
method_s, NULL, 0, NULL, 0, NULL, 0);
}
#endif
/*----------------------------------------------------------------------------*
| BIO with fixed read/write size
@ -93839,6 +94081,144 @@ static int test_dtls_old_seq_number(void)
return EXPECT_RESULT();
}
static int test_dtls13_basic_connection_id(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
&& defined(WOLFSSL_DTLS_CID)
unsigned char client_cid[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
unsigned char server_cid[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned char readBuf[30];
const char* params[] = {
#ifndef NO_SHA256
#ifdef WOLFSSL_AES_128
#ifdef HAVE_AESGCM
"TLS13-AES128-GCM-SHA256",
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
"TLS13-CHACHA20-POLY1305-SHA256",
#endif
#ifdef HAVE_AESCCM
"TLS13-AES128-CCM-8-SHA256",
"TLS13-AES128-CCM-SHA256",
#endif
#endif
#ifdef HAVE_NULL_CIPHER
"TLS13-SHA256-SHA256",
#endif
#endif
};
size_t i;
/* We check if the side included the CID in their output */
#define CLIENT_CID() XMEMMEM(test_ctx.s_buff, test_ctx.s_len, \
client_cid, sizeof(client_cid))
#define SERVER_CID() XMEMMEM(test_ctx.c_buff, test_ctx.c_len, \
server_cid, sizeof(server_cid))
printf("\n");
for (i = 0; i < XELEM_CNT(params) && EXPECT_SUCCESS(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
printf("Testing %s ... ", params[i]);
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i]), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i]), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_c), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, server_cid, sizeof(server_cid)),
1);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_s), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_s, client_cid, sizeof(client_cid)),
1);
/* CH1 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(CLIENT_CID());
/* HRR */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(SERVER_CID());
/* CH2 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(CLIENT_CID());
/* Server first flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(SERVER_CID());
/* Client second flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(CLIENT_CID());
/* Server process flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
/* Client process flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
/* Write some data */
ExpectIntEQ(wolfSSL_write(ssl_c, params[i], XSTRLEN(params[i])),
XSTRLEN(params[i]));
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_write(ssl_s, params[i], XSTRLEN(params[i])),
XSTRLEN(params[i]));
ExpectNotNull(SERVER_CID());
/* Read the data */
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
/* Write short data */
ExpectIntEQ(wolfSSL_write(ssl_c, params[i], 1), 1);
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_write(ssl_s, params[i], 1), 1);
ExpectNotNull(SERVER_CID());
/* Read the short data */
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), 1);
ExpectIntEQ(readBuf[0], params[i][0]);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 1);
ExpectIntEQ(readBuf[0], params[i][0]);
/* Close connection */
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE);
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SHUTDOWN_NOT_DONE);
ExpectNotNull(SERVER_CID());
ExpectIntEQ(wolfSSL_shutdown(ssl_c), 1);
ExpectIntEQ(wolfSSL_shutdown(ssl_s), 1);
if (EXPECT_SUCCESS())
printf("ok\n");
else
printf("failed\n");
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
}
#undef CLIENT_CID
#undef SERVER_CID
#endif
return EXPECT_RESULT();
}
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
defined(HAVE_LIBOQS)
static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx)
@ -96240,6 +96620,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_dtls13_frag_ch_pq),
TEST_DECL(test_dtls_empty_keyshare_with_cookie),
TEST_DECL(test_dtls_old_seq_number),
TEST_DECL(test_dtls13_basic_connection_id),
TEST_DECL(test_tls13_pq_groups),
TEST_DECL(test_tls13_early_data),
TEST_DECL(test_tls_multi_handshakes_one_record),

View File

@ -124,25 +124,6 @@ int link_file(const char* in, const char* out)
#endif
#endif /* !NO_FILESYSTEM */
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) && \
!defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT)
/* This set of memio functions allows for more fine tuned control of the TLS
* connection operations. For new tests, try to use ssl_memio first. */
/* To dump the memory in gdb use
* dump memory client.bin test_ctx.c_buff test_ctx.c_buff+test_ctx.c_len
* dump memory server.bin test_ctx.s_buff test_ctx.s_buff+test_ctx.s_len
* This can be imported into Wireshark by transforming the file with
* od -Ax -tx1 -v client.bin > client.bin.hex
* od -Ax -tx1 -v server.bin > server.bin.hex
* And then loading test_output.dump.hex into Wireshark using the
* "Import from Hex Dump..." option ion and selecting the TCP
* encapsulation option.
*/
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES
#define TEST_MEMIO_BUF_SZ (64 * 1024)
struct test_memio_ctx
{
@ -153,7 +134,6 @@ struct test_memio_ctx
int s_len;
const char* s_ciphers;
};
int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
int max_rounds, int *rounds);
int test_memio_setup(struct test_memio_ctx *ctx,
@ -165,228 +145,6 @@ int test_memio_setup_ex(struct test_memio_ctx *ctx,
byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
byte *serverKey, int serverKeySz);
static WC_INLINE int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz,
void *ctx)
{
struct test_memio_ctx *test_ctx;
byte *buf;
int *len;
test_ctx = (struct test_memio_ctx*)ctx;
if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
buf = test_ctx->c_buff;
len = &test_ctx->c_len;
}
else {
buf = test_ctx->s_buff;
len = &test_ctx->s_len;
}
if ((unsigned)(*len + sz) > TEST_MEMIO_BUF_SZ)
return WOLFSSL_CBIO_ERR_WANT_WRITE;
#ifdef WOLFSSL_DUMP_MEMIO_STREAM
{
WOLFSSL_BIO *dump_file = wolfSSL_BIO_new_file("test_memio.dump", "a");
if (dump_file != NULL) {
(void)wolfSSL_BIO_write(dump_file, data, sz);
wolfSSL_BIO_free(dump_file);
}
}
#endif
XMEMCPY(buf + *len, data, (size_t)sz);
*len += sz;
return sz;
}
static WC_INLINE int test_memio_read_cb(WOLFSSL *ssl, char *data, int sz,
void *ctx)
{
struct test_memio_ctx *test_ctx;
int read_sz;
byte *buf;
int *len;
test_ctx = (struct test_memio_ctx*)ctx;
if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
buf = test_ctx->s_buff;
len = &test_ctx->s_len;
}
else {
buf = test_ctx->c_buff;
len = &test_ctx->c_len;
}
if (*len == 0)
return WOLFSSL_CBIO_ERR_WANT_READ;
read_sz = sz < *len ? sz : *len;
XMEMCPY(data, buf, (size_t)read_sz);
XMEMMOVE(buf, buf + read_sz,(size_t) (*len - read_sz));
*len -= read_sz;
return read_sz;
}
int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
int max_rounds, int *rounds)
{
byte handshake_complete = 0, hs_c = 0, hs_s = 0;
int ret, err;
if (rounds != NULL)
*rounds = 0;
while (!handshake_complete && max_rounds > 0) {
if (!hs_c) {
wolfSSL_SetLoggingPrefix("client");
ret = wolfSSL_connect(ssl_c);
wolfSSL_SetLoggingPrefix(NULL);
if (ret == WOLFSSL_SUCCESS) {
hs_c = 1;
}
else {
err = wolfSSL_get_error(ssl_c, ret);
if (err != WOLFSSL_ERROR_WANT_READ &&
err != WOLFSSL_ERROR_WANT_WRITE)
return -1;
}
}
if (!hs_s) {
wolfSSL_SetLoggingPrefix("server");
ret = wolfSSL_accept(ssl_s);
wolfSSL_SetLoggingPrefix(NULL);
if (ret == WOLFSSL_SUCCESS) {
hs_s = 1;
}
else {
err = wolfSSL_get_error(ssl_s, ret);
if (err != WOLFSSL_ERROR_WANT_READ &&
err != WOLFSSL_ERROR_WANT_WRITE)
return -1;
}
}
handshake_complete = hs_c && hs_s;
max_rounds--;
if (rounds != NULL)
*rounds = *rounds + 1;
}
if (!handshake_complete)
return -1;
return 0;
}
int test_memio_setup_ex(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s,
byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
byte *serverKey, int serverKeySz)
{
int ret;
(void)caCert;
(void)caCertSz;
(void)serverCert;
(void)serverCertSz;
(void)serverKey;
(void)serverKeySz;
if (ctx_c != NULL && *ctx_c == NULL) {
*ctx_c = wolfSSL_CTX_new(method_c());
if (*ctx_c == NULL)
return -1;
#ifndef NO_CERTS
if (caCert == NULL) {
ret = wolfSSL_CTX_load_verify_locations(*ctx_c, caCertFile, 0);
}
else {
ret = wolfSSL_CTX_load_verify_buffer(*ctx_c, caCert, (long)caCertSz,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return -1;
#endif /* NO_CERTS */
wolfSSL_SetIORecv(*ctx_c, test_memio_read_cb);
wolfSSL_SetIOSend(*ctx_c, test_memio_write_cb);
if (ctx->c_ciphers != NULL) {
ret = wolfSSL_CTX_set_cipher_list(*ctx_c, ctx->c_ciphers);
if (ret != WOLFSSL_SUCCESS)
return -1;
}
}
if (ctx_s != NULL && *ctx_s == NULL) {
*ctx_s = wolfSSL_CTX_new(method_s());
if (*ctx_s == NULL)
return -1;
#ifndef NO_CERTS
if (serverKey == NULL) {
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx_s, svrKeyFile,
WOLFSSL_FILETYPE_PEM);
}
else {
ret = wolfSSL_CTX_use_PrivateKey_buffer(*ctx_s, serverKey,
(long)serverKeySz, WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return- -1;
if (serverCert == NULL) {
ret = wolfSSL_CTX_use_certificate_file(*ctx_s, svrCertFile,
WOLFSSL_FILETYPE_PEM);
}
else {
ret = wolfSSL_CTX_use_certificate_chain_buffer_format(*ctx_s,
serverCert, (long)serverCertSz, WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return -1;
#endif /* NO_CERTS */
wolfSSL_SetIORecv(*ctx_s, test_memio_read_cb);
wolfSSL_SetIOSend(*ctx_s, test_memio_write_cb);
if (ctx->s_ciphers != NULL) {
ret = wolfSSL_CTX_set_cipher_list(*ctx_s, ctx->s_ciphers);
if (ret != WOLFSSL_SUCCESS)
return -1;
}
}
if (ctx_c != NULL && ssl_c != NULL) {
*ssl_c = wolfSSL_new(*ctx_c);
if (*ssl_c == NULL)
return -1;
wolfSSL_SetIOWriteCtx(*ssl_c, ctx);
wolfSSL_SetIOReadCtx(*ssl_c, ctx);
}
if (ctx_s != NULL && ssl_s != NULL) {
*ssl_s = wolfSSL_new(*ctx_s);
if (*ssl_s == NULL)
return -1;
wolfSSL_SetIOWriteCtx(*ssl_s, ctx);
wolfSSL_SetIOReadCtx(*ssl_s, ctx);
#if !defined(NO_DH)
SetDH(*ssl_s);
#endif
}
return 0;
}
int test_memio_setup(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s)
{
return test_memio_setup_ex(ctx, ctx_c, ctx_s, ssl_c, ssl_s, method_c,
method_s, NULL, 0, NULL, 0, NULL, 0);
}
#endif
#if !defined(SINGLE_THREADED) && defined(WOLFSSL_COND)
void signal_ready(tcp_ready* ready)
{

View File

@ -3397,6 +3397,26 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n)
}
#endif
void *mymemmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen)
{
size_t i, j;
const char* h = (const char*)haystack;
const char* n = (const char*)needle;
if (needlelen > haystacklen)
return NULL;
for (i = 0; i <= haystacklen - needlelen; i++) {
for (j = 0; j < needlelen; j++) {
if (h[i + j] != n[j])
break;
}
if (j == needlelen)
return (void*)(h + i);
}
return NULL;
}
/* custom memory wrappers */
#ifdef WOLFSSL_NUCLEUS_1_2

View File

@ -1433,7 +1433,7 @@ enum {
/* DTLSv1.3 parsing code copies the record header in a static buffer to decrypt
* the record. Increasing the CID max size does increase also this buffer,
* impacting on per-session runtime memory footprint. */
#define DTLS_CID_MAX_SIZE 2
#define DTLS_CID_MAX_SIZE 10
#endif
#else
#undef DTLS_CID_MAX_SIZE
@ -6647,7 +6647,7 @@ typedef struct CipherSuiteInfo {
#endif
byte cipherSuite0;
byte cipherSuite;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
byte minor;
byte major;
@ -6677,7 +6677,7 @@ WOLFSSL_LOCAL const char* GetCipherNameIana(byte cipherSuite0, byte cipherSuite)
WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl);
WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl);
WOLFSSL_LOCAL int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
byte* cipherSuite, int* flags);
byte* cipherSuite, byte* major, byte* minor, int* flags);
enum encrypt_side {
@ -6828,6 +6828,7 @@ WOLFSSL_LOCAL int Dtls13RlAddCiphertextHeader(WOLFSSL* ssl, byte* out,
word16 length);
WOLFSSL_LOCAL int Dtls13RlAddPlaintextHeader(WOLFSSL* ssl, byte* out,
enum ContentType content_type, word16 length);
WOLFSSL_LOCAL int Dtls13MinimumRecordLength(WOLFSSL* ssl);
WOLFSSL_LOCAL int Dtls13EncryptRecordNumber(WOLFSSL* ssl, byte* hdr,
word16 recordLength);
WOLFSSL_LOCAL int Dtls13IsUnifiedHeader(byte header_flags);

View File

@ -730,6 +730,7 @@ typedef struct w64wrapper {
#define XMEMSET(b,c,l) memset((b),(c),(l))
#define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n))
#define XMEMMOVE(d,s,l) memmove((d),(s),(l))
#define XMEMMEM(h,hl,n,nl) mymemmem((h),(hl),(n),(nl))
#define XSTRLEN(s1) strlen((s1))
#define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))

View File

@ -1214,6 +1214,8 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void);
#ifndef WOLFSSL_LEANPSK
char* mystrnstr(const char* s1, const char* s2, unsigned int n);
#endif
WOLFSSL_API void *mymemmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
#ifndef FILE_BUFFER_SIZE
/* default static file buffer size for input, will use dynamic buffer if