add store finished message on Tls13 (#4381)

* add to store finished message on Tls13

* addressed jenkins failure

* jenkins failures

sanity check for size before copying memory

* remove check of finishSz

* addressed review comments
This commit is contained in:
Hideki Miyazaki 2021-09-14 08:22:16 +09:00 committed by GitHub
parent a65ab0c4af
commit 4d49ab6342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 253 additions and 23 deletions

View File

@ -6795,7 +6795,12 @@ void SSL_ResourceFree(WOLFSSL* ssl)
ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));
}
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
ForceZero(&ssl->clientFinished, TLS_FINISHED_SZ_MAX);
ForceZero(&ssl->serverFinished, TLS_FINISHED_SZ_MAX);
ssl->serverFinished_len = 0;
ssl->clientFinished_len = 0;
#endif
#ifndef NO_DH
if (ssl->buffers.serverDH_Priv.buffer) {
ForceZero(ssl->buffers.serverDH_Priv.buffer,
@ -13186,12 +13191,16 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
}
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
if (ssl->options.side == WOLFSSL_CLIENT_END)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
XMEMCPY(ssl->serverFinished,
input + *inOutIdx, TLS_FINISHED_SZ);
else
ssl->serverFinished_len = TLS_FINISHED_SZ;
}
else {
XMEMCPY(ssl->clientFinished,
input + *inOutIdx, TLS_FINISHED_SZ);
ssl->clientFinished_len = TLS_FINISHED_SZ;
}
#endif
/* force input exhaustion at ProcessReply consuming padSz */
@ -18165,12 +18174,16 @@ int SendFinished(WOLFSSL* ssl)
}
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
if (ssl->options.side == WOLFSSL_CLIENT_END)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
XMEMCPY(ssl->clientFinished,
hashes, TLS_FINISHED_SZ);
else
ssl->clientFinished_len = TLS_FINISHED_SZ;
}
else {
XMEMCPY(ssl->serverFinished,
hashes, TLS_FINISHED_SZ);
ssl->serverFinished_len = TLS_FINISHED_SZ;
}
#endif
#ifdef WOLFSSL_DTLS

View File

@ -28316,37 +28316,44 @@ int wolfSSL_i2d_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT *a, unsigned char **pp)
WOLFSSL_API size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count)
{
WOLFSSL_ENTER("SSL_get_finished");
byte len = 0;
if (!ssl || !buf || count < TLS_FINISHED_SZ) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
if (ssl->options.side == WOLFSSL_SERVER_END)
XMEMCPY(buf, ssl->serverFinished,
TLS_FINISHED_SZ);
else
XMEMCPY(buf, ssl->clientFinished,
TLS_FINISHED_SZ);
return TLS_FINISHED_SZ;
if (ssl->options.side == WOLFSSL_SERVER_END) {
len = ssl->serverFinished_len;
XMEMCPY(buf, ssl->serverFinished, len);
}
else {
len = ssl->clientFinished_len;
XMEMCPY(buf, ssl->clientFinished, len);
}
return len;
}
WOLFSSL_API size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count)
{
byte len = 0;
WOLFSSL_ENTER("SSL_get_peer_finished");
if (!ssl || !buf || count < TLS_FINISHED_SZ) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
if (ssl->options.side == WOLFSSL_CLIENT_END)
XMEMCPY(buf, ssl->serverFinished,
TLS_FINISHED_SZ);
else
XMEMCPY(buf, ssl->clientFinished,
TLS_FINISHED_SZ);
return TLS_FINISHED_SZ;
if (ssl->options.side == WOLFSSL_CLIENT_END) {
len = ssl->serverFinished_len;
XMEMCPY(buf, ssl->serverFinished, len);
}
else {
len = ssl->clientFinished_len;
XMEMCPY(buf, ssl->clientFinished, len);
}
return len;
}
#endif /* WOLFSSL_HAPROXY */

View File

@ -6868,6 +6868,16 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (sniff == NO_SNIFF) {
ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz);
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
XMEMCPY(ssl->serverFinished, mac, finishedSz);
ssl->serverFinished_len = finishedSz;
}
else {
XMEMCPY(ssl->clientFinished, mac, finishedSz);
ssl->clientFinished_len = finishedSz;
}
#endif
if (ret != 0)
return ret;
if (size != finishedSz)
@ -6983,7 +6993,16 @@ static int SendTls13Finished(WOLFSSL* ssl)
ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL);
if (ret != 0)
return ret;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
XMEMCPY(ssl->clientFinished, &input[headerSz], finishedSz);
ssl->clientFinished_len = finishedSz;
}
else {
XMEMCPY(ssl->serverFinished, &input[headerSz], finishedSz);
ssl->serverFinished_len = finishedSz;
}
#endif
/* This message is always encrypted. */
sendSz = BuildTls13Message(ssl, output, outputSz, input,
headerSz + finishedSz, handshake, 1, 0, 0);

View File

@ -3803,6 +3803,13 @@ static int nonblocking_accept_read(void* args, WOLFSSL* ssl, SOCKET_T* sockfd)
}
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
#define MD_MAX_SIZE WC_SHA512_DIGEST_SIZE
byte server_side_msg1[MD_MAX_SIZE] = {0};/* msg sent by server */
byte server_side_msg2[MD_MAX_SIZE] = {0};/* msg received from client */
byte client_side_msg1[MD_MAX_SIZE] = {0};/* msg sent by client */
byte client_side_msg2[MD_MAX_SIZE] = {0};/* msg received from server */
#endif
static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
{
SOCKET_T sockfd = 0;
@ -3818,6 +3825,9 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
int idx;
int ret, err = 0;
int sharedCtx = 0;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
size_t msg_len = 0;
#endif
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
@ -4001,6 +4011,15 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
goto done;
}
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
XMEMSET(server_side_msg2, 0, MD_MAX_SIZE);
msg_len = wolfSSL_get_peer_finished(ssl, server_side_msg2, MD_MAX_SIZE);
AssertIntGE(msg_len, 0);
XMEMSET(server_side_msg1, 0, MD_MAX_SIZE);
msg_len = wolfSSL_get_finished(ssl, server_side_msg1, MD_MAX_SIZE);
AssertIntGE(msg_len, 0);
#endif
idx = wolfSSL_read(ssl, input, sizeof(input)-1);
if (idx > 0) {
input[idx] = '\0';
@ -5239,6 +5258,171 @@ static void test_wolfSSL_CTX_verifyDepth_ServerClient(void)
#endif /* (OPENSSL_EXTRA) && !(WOLFSSL_TIRTOS) && (NO_WOLFSSL_CLIENT) */
}
static void test_client_get_finished(void* args, cbType cb)
{
(void) args;
(void) cb;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
SOCKET_T sockfd = 0;
callback_functions* cbf;
WOLFSSL_CTX* ctx = 0;
WOLFSSL* ssl = 0;
char msg[64] = "hello wolfssl!";
char reply[1024];
int input;
int msgSz = (int)XSTRLEN(msg);
int ret, err = 0;
WOLFSSL_METHOD* method = NULL;
size_t msg_len = 0;
((func_args*)args)->return_code = TEST_FAIL;
cbf = ((func_args*)args)->callbacks;
if (cbf != NULL && cbf->method != NULL) {
method = cbf->method();
}
else {
method = wolfSSLv23_client_method();
}
ctx = wolfSSL_CTX_new(method);
/* Do connect here so server detects failures */
tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port,
0, 0, NULL);
if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS)
{
/* err_sys("can't load ca file, Please run from wolfSSL home dir");*/
goto done;
}
if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile,
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) {
goto done;
}
if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile,
WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) {
goto done;
}
/* call ctx setup callback */
if (cbf != NULL && cbf->ctx_ready != NULL) {
cbf->ctx_ready(ctx);
}
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
goto done;
}
if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
goto done;
}
/* call ssl setup callback */
if (cbf != NULL && cbf->ssl_ready != NULL) {
cbf->ssl_ready(ssl);
}
do {
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) { break; } else if (ret == 0) { continue; }
}
#endif
err = 0; /* Reset error */
ret = wolfSSL_connect(ssl);
if (ret != WOLFSSL_SUCCESS) {
err = wolfSSL_get_error(ssl, 0);
}
} while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E);
if (ret != WOLFSSL_SUCCESS) {
char buff[WOLFSSL_MAX_ERROR_SZ];
printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff));
goto done;
}
/* get_finished test */
/* 1. get own sent message */
XMEMSET(client_side_msg1, 0, MD_MAX_SIZE);
msg_len = wolfSSL_get_finished(ssl, client_side_msg1, MD_MAX_SIZE);
AssertIntGE(msg_len, 0);
/* 2. get peer message */
XMEMSET(client_side_msg2, 0, MD_MAX_SIZE);
msg_len = wolfSSL_get_peer_finished(ssl, client_side_msg2, MD_MAX_SIZE);
AssertIntGE(msg_len, 0);
if (cb != NULL)
(cb)(ctx, ssl);
if (wolfSSL_write(ssl, msg, msgSz) != msgSz) {
/*err_sys("SSL_write failed");*/
goto done;
}
input = wolfSSL_read(ssl, reply, sizeof(reply)-1);
if (input > 0) {
reply[input] = '\0';
printf("Server response: %s\n", reply);
}
((func_args*)args)->return_code = TEST_SUCCESS;
done:
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
CloseSocket(sockfd);
return;
#endif
}
static void test_wolfSSL_get_finished(void)
{
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS)
tcp_ready ready;
func_args client_args;
func_args server_args;
THREAD_TYPE serverThread;
XMEMSET(&client_args, 0, sizeof(func_args));
XMEMSET(&server_args, 0, sizeof(func_args));
StartTCP();
InitTcpReady(&ready);
#if defined(USE_WINDOWS_API)
/* use RNG to get random port if using windows */
ready.port = GetRandomPort();
#endif
server_args.signal = &ready;
client_args.signal = &ready;
start_thread(test_server_nofail, &server_args, &serverThread);
wait_tcp_ready(&server_args);
test_client_get_finished(&client_args, NULL);
join_thread(serverThread);
AssertTrue(client_args.return_code);
AssertTrue(server_args.return_code);
/* test received msg vs sent msg */
AssertIntEQ(0, XMEMCMP(client_side_msg1, server_side_msg2, MD_MAX_SIZE));
AssertIntEQ(0, XMEMCMP(client_side_msg2, server_side_msg1, MD_MAX_SIZE));
FreeTcpReady(&ready);
#else
(void)test_client_get_finished;
#endif
}
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT)
/* canned export of a session using older version 3 */
@ -48547,6 +48731,9 @@ void ApiTest(void)
#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \
(!defined(NO_RSA) || defined(HAVE_ECC))
test_for_double_Free();
#endif
#ifdef HAVE_IO_TESTS_DEPENDENCIES
test_wolfSSL_get_finished();
#endif
test_SSL_CIPHER_get_xxx();
test_wolfSSL_ERR_strings();

View File

@ -1376,6 +1376,8 @@ enum Misc {
/* max size of buffer for exporting state */
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
TLS_FINISHED_SZ_MAX = WC_MAX_DIGEST_SIZE,
/* longest message digest size is SHA512, 64 */
EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */
MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
KEY_LABEL_SZ = 13, /* TLS key block expansion sz */
@ -4538,8 +4540,10 @@ struct WOLFSSL {
* used in the EST protocol to bind an enrollment to a TLS session through
* 'proof-of-possession' (https://tools.ietf.org/html/rfc7030#section-3.4
* and https://tools.ietf.org/html/rfc7030#section-3.5). */
byte clientFinished[TLS_FINISHED_SZ];
byte serverFinished[TLS_FINISHED_SZ];
byte clientFinished[TLS_FINISHED_SZ_MAX];
byte serverFinished[TLS_FINISHED_SZ_MAX];
byte clientFinished_len;
byte serverFinished_len;
#endif
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names;