Improve PSK timeout checks

Post-handshake Authentication

Fix KeyUpdate to derive keys properly

Fix supported curves (not checking ctx extensions)
This commit is contained in:
Sean Parkinson
2017-06-08 10:32:51 +10:00
committed by David Garske
parent 6d5c257010
commit 89e6ac91bf
11 changed files with 692 additions and 212 deletions

View File

@ -72,15 +72,19 @@
static int NonBlockingSSL_Connect(WOLFSSL* ssl)
{
#ifndef WOLFSSL_CALLBACKS
int ret = wolfSSL_connect(ssl);
#else
int ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout);
#endif
int error = wolfSSL_get_error(ssl, 0);
SOCKET_T sockfd = (SOCKET_T)wolfSSL_get_fd(ssl);
int ret;
int error;
SOCKET_T sockfd;
int select_ret = 0;
#ifndef WOLFSSL_CALLBACKS
ret = wolfSSL_connect(ssl);
#else
ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout);
#endif
error = wolfSSL_get_error(ssl, 0);
sockfd = (SOCKET_T)wolfSSL_get_fd(ssl);
while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ ||
error == SSL_ERROR_WANT_WRITE ||
error == WC_PENDING_E)) {
@ -551,6 +555,60 @@ static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown)
return SSL_SUCCESS;
}
static void ClientWrite(WOLFSSL* ssl, char* msg, int msgSz)
{
int ret, err;
char buffer[WOLFSSL_MAX_ERROR_SZ];
do {
err = 0; /* reset error */
ret = wolfSSL_write(ssl, msg, msgSz);
if (ret <= 0) {
err = wolfSSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
#endif
}
} while (err == WC_PENDING_E);
if (ret != msgSz) {
printf("SSL_write msg error %d, %s\n", err,
wolfSSL_ERR_error_string(err, buffer));
err_sys("SSL_write failed");
}
}
static void ClientRead(WOLFSSL* ssl, char* reply, int replyLen, int mustRead)
{
int ret, err;
char buffer[WOLFSSL_MAX_ERROR_SZ];
do {
err = 0; /* reset error */
ret = wolfSSL_read(ssl, reply, replyLen);
if (ret <= 0) {
err = wolfSSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
else
#endif
if (err != SSL_ERROR_WANT_READ) {
printf("SSL_read reply error %d, %s\n", err,
wolfSSL_ERR_error_string(err, buffer));
err_sys("SSL_read failed");
}
}
} while (err == WC_PENDING_E || (mustRead && err == SSL_ERROR_WANT_READ));
if (ret > 0) {
reply[ret] = 0;
printf("%s\n", reply);
}
}
static void Usage(void)
{
@ -655,6 +713,9 @@ static void Usage(void)
#ifdef HAVE_CURVE25519
printf("-t Use X25519 for key exchange\n");
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
printf("-Q Support requesting certificate post-handshake\n");
#endif
}
THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
@ -751,6 +812,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int helloRetry = 0;
int onlyKeyShare = 0;
int noPskDheKe = 0;
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
int postHandAuth = 0;
#endif
#endif
int updateKeysIVs = 0;
@ -797,10 +861,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
StackTrap();
#ifndef WOLFSSL_VXWORKS
/* Not used: t, Q */
/* Not used: All used */
while ((ch = mygetopt(argc, argv, "?"
"ab:c:defgh:ijk:l:mnop:q:rstuv:wxyz"
"A:B:CDE:F:GHIJKL:M:NO:PRS:TUVW:XYZ:")) != -1) {
"A:B:CDE:F:GHIJKL:M:NO:PQRS:TUVW:XYZ:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -1107,6 +1171,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
case 't' :
#ifdef HAVE_CURVE25519
useX25519 = 1;
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECC)
onlyKeyShare = 2;
#endif
#endif
break;
case 'Q' :
#if defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_POST_HANDSHAKE_AUTH)
postHandAuth = 1;
#endif
break;
@ -1533,6 +1607,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
if (noPskDheKe)
wolfSSL_CTX_no_dhe_psk(ctx);
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth)
wolfSSL_CTX_allow_post_handshake_auth(ctx);
#endif
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
@ -1846,76 +1924,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
wolfSSL_update_keys(ssl);
#endif
do {
err = 0; /* reset error */
ret = wolfSSL_write(ssl, msg, msgSz);
if (ret <= 0) {
err = wolfSSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
#endif
}
} while (err == WC_PENDING_E);
if (ret != msgSz) {
printf("SSL_write msg error %d, %s\n", err,
wolfSSL_ERR_error_string(err, buffer));
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
err_sys("SSL_write failed");
}
ClientWrite(ssl, msg, msgSz);
do {
err = 0; /* reset error */
ret = wolfSSL_read(ssl, reply, sizeof(reply)-1);
if (ret <= 0) {
err = wolfSSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
#endif
}
} while (err == WC_PENDING_E || err == SSL_ERROR_WANT_READ);
if (ret > 0) {
reply[ret] = 0;
printf("Server response: %s\n", reply);
ClientRead(ssl, reply, sizeof(reply)-1, 1);
if (sendGET) { /* get html */
while (1) {
do {
err = 0; /* reset error */
ret = wolfSSL_read(ssl, reply, sizeof(reply)-1);
if (ret <= 0) {
err = wolfSSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
#endif
}
} while (err == WC_PENDING_E);
if (ret > 0) {
reply[ret] = 0;
printf("%s\n", reply);
}
else
break;
}
}
}
if (ret < 0) {
if (err != SSL_ERROR_WANT_READ) {
printf("SSL_read reply error %d, %s\n", err,
wolfSSL_ERR_error_string(err, buffer));
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
err_sys("SSL_read failed");
}
if (sendGET) { /* get html */
ClientRead(ssl, reply, sizeof(reply)-1, 0);
}
#ifndef NO_SESSION_CACHE

View File

@ -240,6 +240,63 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int throughput)
return EXIT_SUCCESS;
}
static void ServerRead(WOLFSSL* ssl, char* input, int inputLen)
{
int ret, err;
char buffer[CYASSL_MAX_ERROR_SZ];
/* Read data */
do {
err = 0; /* reset error */
ret = SSL_read(ssl, input, inputLen);
if (ret < 0) {
err = SSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
else
#endif
if (err != SSL_ERROR_WANT_READ) {
printf("SSL_read input error %d, %s\n", err,
ERR_error_string(err, buffer));
err_sys("SSL_read failed");
}
}
} while (err == WC_PENDING_E);
if (ret > 0) {
input[ret] = 0; /* null terminate message */
printf("Client message: %s\n", input);
}
}
static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen)
{
int ret, err;
char buffer[CYASSL_MAX_ERROR_SZ];
do {
err = 0; /* reset error */
ret = SSL_write(ssl, output, outputLen);
if (ret <= 0) {
err = SSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
#endif
}
} while (err == WC_PENDING_E || err == SSL_ERROR_WANT_WRITE);
if (ret != outputLen) {
printf("SSL_write msg error %d, %s\n", err,
ERR_error_string(err, buffer));
err_sys("SSL_write failed");
}
}
static void Usage(void)
{
@ -307,6 +364,9 @@ static void Usage(void)
#ifdef WOLFSSL_TLS13
printf("-K Key Exchange for PSK not using (EC)DHE\n");
printf("-U Update keys and IVs before sending\n");
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
printf("-Q Request certificate from client post-handshake\n");
#endif
#endif
}
@ -393,6 +453,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
int noPskDheKe = 0;
#endif
int updateKeysIVs = 0;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
int postHandAuth = 0;
#endif
#ifdef WOLFSSL_STATIC_MEMORY
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
@ -437,10 +500,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#ifdef WOLFSSL_VXWORKS
useAnyAddr = 1;
#else
/* Not Used: h, m, t, x, y, z, F, J, M, Q, T, V, W, X, Y */
/* Not Used: h, m, t, x, y, z, F, J, M, T, V, W, X, Y */
while ((ch = mygetopt(argc, argv, "?"
"abc:defgijk:l:nop:q:rsuv:w"
"A:B:C:D:E:GHIKL:NO:PR:S:UYZ:")) != -1) {
"A:B:C:D:E:GHIKL:NO:PQR:S:UYZ:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -654,6 +717,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#endif
break;
case 'Q' :
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
postHandAuth = 1;
doCliCertCheck = 0;
#endif
break;
default:
Usage();
exit(MY_EX_USAGE);
@ -1180,40 +1250,43 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
free(list);
}
#endif
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth) {
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |
((usePskPlus)? SSL_VERIFY_FAIL_EXCEPT_PSK :
SSL_VERIFY_FAIL_IF_NO_PEER_CERT),0);
if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0)
!= SSL_SUCCESS) {
err_sys("can't load ca file, Please run from wolfSSL home dir");
}
#ifdef WOLFSSL_TRUST_PEER_CERT
if (trustCert) {
if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert,
SSL_FILETYPE_PEM)) != SSL_SUCCESS) {
err_sys("can't load trusted peer cert file");
}
}
#endif /* WOLFSSL_TRUST_PEER_CERT */
}
#endif
#endif
if (echoData == 0 && throughput == 0) {
const char* write_msg;
int write_msg_sz;
/* Read data */
do {
err = 0; /* reset error */
ret = SSL_read(ssl, input, sizeof(input)-1);
if (ret < 0) {
err = SSL_get_error(ssl, 0);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
else
#endif
if (err != SSL_ERROR_WANT_READ) {
printf("SSL_read input error %d, %s\n", err,
ERR_error_string(err, buffer));
err_sys("SSL_read failed");
}
}
} while (err == WC_PENDING_E);
if (ret > 0) {
input[ret] = 0; /* null terminate message */
printf("Client message: %s\n", input);
}
ServerRead(ssl, input, sizeof(input)-1);
#ifdef WOLFSSL_TLS13
if (updateKeysIVs)
wolfSSL_update_keys(ssl);
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth)
wolfSSL_request_certificate(ssl);
#endif
/* Write data */
if (!useWebServerMsg) {
@ -1224,25 +1297,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
write_msg = webServerMsg;
write_msg_sz = sizeof(webServerMsg);
}
do {
err = 0; /* reset error */
ret = SSL_write(ssl, write_msg, write_msg_sz);
if (ret <= 0) {
err = SSL_get_error(ssl, 0);
ServerWrite(ssl, write_msg, write_msg_sz);
#ifdef WOLFSSL_ASYNC_CRYPT
if (err == WC_PENDING_E) {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
if (ret < 0) break;
}
#endif
}
} while (err == WC_PENDING_E || err == SSL_ERROR_WANT_WRITE);
if (ret != write_msg_sz) {
printf("SSL_write msg error %d, %s\n", err,
ERR_error_string(err, buffer));
err_sys("SSL_write failed");
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth) {
ServerWrite(ssl, write_msg, write_msg_sz);
ServerRead(ssl, input, sizeof(input)-1);
}
#endif
}
else {
ServerEchoData(ssl, clientfd, echoData, throughput);

View File

@ -4131,10 +4131,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->options.useClientOrder = ctx->useClientOrder;
#ifdef WOLFSSL_TLS13
#ifdef HAVE_SESSION_TICKET
ssl->options.noTicketTls13 = ctx->noTicketTls13;
#endif
#ifdef HAVE_SESSION_TICKET
ssl->options.noTicketTls13 = ctx->noTicketTls13;
#endif
ssl->options.noPskDheKe = ctx->noPskDheKe;
#if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ssl->options.postHandshakeAuth = ctx->postHandshakeAuth;
#endif
#endif
#ifdef HAVE_TLS_EXTENSIONS
@ -4628,6 +4631,14 @@ void SSL_ResourceFree(WOLFSSL* ssl)
}
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
while (ssl->certReqCtx != NULL) {
CertReqCtx* curr = ssl->certReqCtx;
ssl->certReqCtx = curr->next;
XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
#ifdef WOLFSSL_STATIC_MEMORY
/* check if using fixed io buffers and free them */
if (ssl->heap != NULL) {
@ -7533,13 +7544,35 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz
}
#endif
#ifndef NO_WOLFSSL_SERVER
/* Must contain value sent in request when received from client. */
/* Must contain value sent in request. */
if (ssl->options.side == WOLFSSL_SERVER_END) {
if (ssl->clientCertCtx.length != ctxSz ||
XMEMCMP(ssl->clientCertCtx.buffer,
input + args->idx, ctxSz) != 0) {
if (ssl->options.handShakeState != HANDSHAKE_DONE &&
ctxSz != 0) {
return INVALID_CERT_CTX_E;
}
else if (ssl->options.handShakeState == HANDSHAKE_DONE) {
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
CertReqCtx* curr = ssl->certReqCtx;
CertReqCtx* prev = NULL;
while (curr != NULL) {
if ((ctxSz == curr->len) &&
XMEMCMP(&curr->ctx, input + args->idx, ctxSz)
== 0) {
if (prev != NULL)
prev->next = curr->next;
else
ssl->certReqCtx = curr->next;
XFREE(curr, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
break;
}
prev = curr;
curr = curr->next;
}
if (curr == NULL)
#endif
return INVALID_CERT_CTX_E;
}
}
#endif
args->idx += ctxSz;
@ -13836,6 +13869,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case KEY_SHARE_ERROR:
return "Key share extension did not contain a valid named group";
case POST_HAND_AUTH_ERROR:
return "Client will not do post handshake authentication";
default :
return "unknown error number";
}

View File

@ -846,13 +846,25 @@ int wolfSSL_negotiate(WOLFSSL* ssl)
WOLFSSL_ENTER("wolfSSL_negotiate");
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END)
err = wolfSSL_accept(ssl);
if (ssl->options.side == WOLFSSL_SERVER_END) {
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(ssl->version))
err = wolfSSL_accept_TLSv13(ssl);
else
#endif
err = wolfSSL_accept(ssl);
}
#endif
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END)
err = wolfSSL_connect(ssl);
if (ssl->options.side == WOLFSSL_CLIENT_END) {
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(ssl->version))
err = wolfSSL_connect_TLSv13(ssl);
else
#endif
err = wolfSSL_connect(ssl);
}
#endif
WOLFSSL_LEAVE("wolfSSL_negotiate", err);

181
src/tls.c
View File

@ -6327,6 +6327,108 @@ int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes)
#endif
/******************************************************************************/
/* Post-Handshake Authentication */
/******************************************************************************/
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
/* Get the size of the encoded Post-Hanshake Authentication extension.
* Only in ClientHello.
*
* msgType The type of the message this extension is being written into.
* returns the number of bytes of the encoded key share extension.
*/
static word16 TLSX_PostHandAuth_GetSize(byte msgType)
{
if (msgType == client_hello)
return OPAQUE8_LEN;
return SANITY_MSG_E;
}
/* Writes the Post-Handshake Authentication extension into the output buffer.
* Assumes that the the output buffer is big enough to hold data.
* Only in ClientHello.
*
* output The buffer to write into.
* msgType The type of the message this extension is being written into.
* returns the number of bytes written into the buffer.
*/
static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType)
{
if (msgType == client_hello) {
*output = 0;
return OPAQUE8_LEN;
}
return SANITY_MSG_E;
}
/* Parse the Post-Handshake Authentication extension.
* Only in ClientHello.
*
* ssl The SSL/TLS object.
* input The extension data.
* length The length of the extension data.
* msgType The type of the message this extension is being parsed from.
* returns 0 on success and other values indicate failure.
*/
static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte msgType)
{
byte len;
if (msgType == client_hello) {
/* Ensure length byte exists. */
if (length < OPAQUE8_LEN)
return BUFFER_E;
len = input[0];
if (length - OPAQUE8_LEN != len || len != 0)
return BUFFER_E;
ssl->options.postHandshakeAuth = 1;
return 0;
}
return SANITY_MSG_E;
}
/* Create a new Post-handshake authentication object in the extensions.
*
* ssl The SSL/TLS object.
* returns 0 on success and other values indicate failure.
*/
static int TLSX_PostHandAuth_Use(WOLFSSL* ssl)
{
int ret = 0;
TLSX* extension;
/* Find the PSK key exchange modes extension if it exists. */
extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH);
if (extension == NULL) {
/* Push new Post-handshake Authentication extension. */
ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL,
ssl->heap);
if (ret != 0)
return ret;
}
return 0;
}
#define PHA_GET_SIZE TLSX_PostHandAuth_GetSize
#define PHA_WRITE TLSX_PostHandAuth_Write
#define PHA_PARSE TLSX_PostHandAuth_Parse
#else
#define PHA_GET_SIZE(a) 0
#define PHA_WRITE(a, b) 0
#define PHA_PARSE(a, b, c, d) 0
#endif
/******************************************************************************/
/* TLS Extensions Framework */
/******************************************************************************/
@ -6412,6 +6514,11 @@ void TLSX_FreeAll(TLSX* list, void* heap)
case TLSX_PSK_KEY_EXCHANGE_MODES:
break;
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
case TLSX_POST_HANDSHAKE_AUTH:
break;
#endif
#endif
}
@ -6520,6 +6627,11 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType)
length += PKM_GET_SIZE(extension->val, msgType);
break;
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
case TLSX_POST_HANDSHAKE_AUTH:
length += PHA_GET_SIZE(msgType);
break;
#endif
#endif
}
@ -6650,6 +6762,12 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
offset += PKM_WRITE(extension->val, output + offset, msgType);
break;
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
case TLSX_POST_HANDSHAKE_AUTH:
WOLFSSL_MSG("Post-Handshake Authentication extension to write");
offset += PHA_WRITE(output + offset, msgType);
break;
#endif
#endif
}
@ -6949,7 +7067,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
#endif
#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
if (!ssl->options.userCurves && !ssl->ctx->userCurves) {
if (!ssl->options.userCurves && !ssl->ctx->userCurves &&
TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) {
#ifndef HAVE_FIPS
#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
@ -7045,10 +7164,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */
} /* is not server */
WOLFSSL_MSG("Adding signature algorithms extension");
if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl,
ssl->heap)) != 0)
WOLFSSL_MSG("Adding signature algorithms extension");
if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap))
!= 0) {
return ret;
}
#ifdef WOLFSSL_TLS13
if (!isServer && IsAtLeastTLSv1_3(ssl->version)) {
@ -7059,7 +7179,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
return ret;
#ifdef HAVE_SUPPORTED_CURVES
if (!ssl->options.userCurves && !ssl->ctx->userCurves) {
if (!ssl->options.userCurves && !ssl->ctx->userCurves &&
TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS)
== NULL) {
/* Add FFDHE supported groups. */
#ifdef HAVE_FFDHE_2048
ret = TLSX_UseSupportedCurve(&ssl->extensions,
@ -7096,33 +7218,33 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
#endif
if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) {
#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
!defined(NO_ECC_SECP)
#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
!defined(NO_ECC_SECP)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP256R1, 0, NULL,
NULL);
#elif defined(HAVE_CURVE25519)
#elif defined(HAVE_CURVE25519)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_X25519, 0, NULL, NULL);
#elif (!defined(NO_ECC384) || defined(HAVE_ALL_CURVES)) && \
!defined(NO_ECC_SECP)
#elif (!defined(NO_ECC384) || defined(HAVE_ALL_CURVES)) && \
!defined(NO_ECC_SECP)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP384R1, 0, NULL,
NULL);
#elif (!defined(NO_ECC521) || defined(HAVE_ALL_CURVES)) && \
!defined(NO_ECC_SECP)
#elif (!defined(NO_ECC521) || defined(HAVE_ALL_CURVES)) && \
!defined(NO_ECC_SECP)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP521R1, 0, NULL,
NULL);
#elif defined(HAVE_FFDHE_2048)
#elif defined(HAVE_FFDHE_2048)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_2048, 0, NULL, NULL);
#elif defined(HAVE_FFDHE_3072)
#elif defined(HAVE_FFDHE_3072)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_3072, 0, NULL, NULL);
#elif defined(HAVE_FFDHE_4096)
#elif defined(HAVE_FFDHE_4096)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_4096, 0, NULL, NULL);
#elif defined(HAVE_FFDHE_6144)
#elif defined(HAVE_FFDHE_6144)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_6144, 0, NULL, NULL);
#elif defined(HAVE_FFDHE_8192)
#elif defined(HAVE_FFDHE_8192)
ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_8192, 0, NULL, NULL);
#else
#else
ret = KEY_SHARE_ERROR;
#endif
#endif
if (ret != 0)
return ret;
}
@ -7187,6 +7309,13 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
return ret;
}
#endif
#if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (!isServer && ssl->options.postHandshakeAuth) {
ret = TLSX_PostHandAuth_Use(ssl);
if (ret != 0)
return ret;
}
#endif
}
#endif
@ -7673,6 +7802,20 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
ret = PKM_PARSE(ssl, input + offset, size, msgType);
break;
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
case TLSX_POST_HANDSHAKE_AUTH:
WOLFSSL_MSG("PSK Key Exchange Modes extension received");
if (!IsAtLeastTLSv1_3(ssl->version))
break;
if (IsAtLeastTLSv1_3(ssl->version) &&
msgType != client_hello) {
return EXT_NOT_ALLOWED;
}
ret = PHA_PARSE(ssl, input + offset, size, msgType);
break;
#endif
#endif
}

View File

@ -784,9 +784,9 @@ static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] =
static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret)
{
WOLFSSL_MSG("Derive New Application Traffic Secret");
return DeriveKeyMsg(ssl, secret, -1, secret,
appTrafficLabel, APP_TRAFFIC_LABEL_SZ,
NULL, 0, ssl->specs.mac_algorithm);
return DeriveKey(ssl, secret, -1, secret,
appTrafficLabel, APP_TRAFFIC_LABEL_SZ,
ssl->specs.mac_algorithm, 0);
}
/* Derive the early secret using HKDF Extract.
@ -2607,10 +2607,13 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input,
static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size)
{
word16 len;
word32 begin = *inOutIdx;
int ret;
Suites peerSuites;
word16 len;
word32 begin = *inOutIdx;
int ret;
Suites peerSuites;
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
CertReqCtx* certReqCtx;
#endif
WOLFSSL_ENTER("DoTls13CertificateRequest");
@ -2629,14 +2632,21 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
if (ssl->options.connectState < FINISHED_DONE && len > 0)
return BUFFER_ERROR;
/* Request context parsed here. */
/* TODO: [TLS13] Request context for post-handshake auth.
* Store the value and return it in Certificate message.
* Must be unique in the scope of the connection.
*/
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
certReqCtx = XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (certReqCtx == NULL)
return MEMORY_E;
certReqCtx->next = ssl->certReqCtx;
certReqCtx->len = len;
XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len);
ssl->certReqCtx = certReqCtx;
#endif
*inOutIdx += len;
/* TODO: [TLS13] Add extension handling. */
/* TODO: Add support for more extensions:
* signed_certificate_timestamp, certificate_authorities, oid_filters.
*/
/* Certificate extensions */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
@ -2644,6 +2654,8 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
*inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + len > size)
return BUFFER_ERROR;
if (len == 0)
return INVALID_PARAMETER;
if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len,
certificate_request, &peerSuites)))
return ret;
@ -2651,11 +2663,25 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, peerSuites.hashSigAlgoSz);
ssl->options.sendVerify = SEND_CERT;
if (ssl->buffers.certificate && ssl->buffers.certificate->buffer &&
ssl->buffers.key && ssl->buffers.key->buffer)
ssl->options.sendVerify = SEND_CERT;
else
ssl->options.sendVerify = SEND_BLANK_CERT;
/* This message is always encrypted so add encryption padding. */
*inOutIdx += ssl->keys.padSz;
#if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->options.handShakeState == HANDSHAKE_DONE) {
/* reset handshake states */
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
ssl->options.connectState = FIRST_REPLY_DONE;
ssl->options.handShakeState = CLIENT_HELLO_COMPLETE;
}
#endif
return ret;
}
@ -2719,11 +2745,14 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
#ifdef HAVE_SESSION_TICKET
/* Decode the identity. */
if ((ret = DoClientTicket(ssl, current->identity, current->identityLen)) == WOLFSSL_TICKET_RET_OK) {
/* Check the ticket isn't too old or new. */
int diff = TimeNowInMilliseconds() - ssl->session.ticketSeen;
word32 now = TimeNowInMilliseconds();
int diff = now - ssl->session.ticketSeen;
diff -= current->ticketAge - ssl->session.ticketAdd;
/* TODO: [TLS13] What should the value be? Configurable? */
if (diff < -1000 || diff > 1000) {
/* Check session and ticket age timeout.
* Allow +/- 1000 milliseconds on ticket age.
*/
if ((ssl->session.bornOn + ssl->session.timeout) * 1000 >= now ||
diff < -1000 || diff - MAX_TICKET_AGE_SECS * 1000 > 1000) {
/* Invalid difference, fallback to full handshake. */
ssl->options.resuming = 0;
break;
@ -3268,15 +3297,16 @@ int SendTls13EncryptedExtensions(WOLFSSL* ssl)
* This message is always encrypted in TLS v1.3.
* Only a server will send this message.
*
* ssl The SSL/TLS object.
* ssl SSL/TLS object.
* reqCtx Request context.
* reqCtxLen Length of context. 0 when sending as part of handshake.
* returns 0 on success, otherwise failure.
*/
int SendTls13CertificateRequest(WOLFSSL* ssl)
int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, int reqCtxLen)
{
byte* output;
int ret;
int sendSz;
int reqCtxLen = 0;
word32 i;
int reqSz;
@ -3305,10 +3335,11 @@ int SendTls13CertificateRequest(WOLFSSL* ssl)
AddTls13Headers(output, reqSz, certificate_request, ssl);
/* Certificate request context. */
/* TODO: [TLS13] Request context for post-handshake auth.
* Must be unique in the scope of the connection.
*/
output[i++] = reqCtxLen;
if (reqCtxLen != 0) {
XMEMCPY(output + i, reqCtx, reqCtxLen);
i += reqCtxLen;
}
/* Certificate extensions. */
i += TLSX_WriteResponse(ssl, output + i, certificate_request);
@ -3801,12 +3832,17 @@ int SendTls13Certificate(WOLFSSL* ssl)
word32 idx = 0;
word32 offset = OPAQUE16_LEN;
byte* p = NULL;
byte certReqCtxLen = 0;
byte* certReqCtx = NULL;
WOLFSSL_ENTER("SendTls13Certificate");
/* TODO: [TLS13] Request context for post-handshake auth.
* Taken from request if post-handshake.
*/
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
certReqCtxLen = ssl->certReqCtx->len;
certReqCtx = &ssl->certReqCtx->ctx;
}
#endif
if (ssl->options.sendVerify == SEND_BLANK_CERT) {
certSz = 0;
@ -3822,8 +3858,9 @@ int SendTls13Certificate(WOLFSSL* ssl)
}
/* Certificate Data */
certSz = ssl->buffers.certificate->length;
/* Cert Req Ctx Len | Cert List Len | Cert Data Len */
headerSz = OPAQUE8_LEN + CERT_HEADER_SZ + CERT_HEADER_SZ;
/* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
CERT_HEADER_SZ;
/* Length of message data with one certificate and empty extensions. */
length = headerSz + certSz + OPAQUE16_LEN;
/* Length of list data with one certificate and empty extensions. */
@ -3892,9 +3929,13 @@ int SendTls13Certificate(WOLFSSL* ssl)
AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
/* Request context. */
output[i++] = 0;
length -= 1;
fragSz -= 1;
output[i++] = certReqCtxLen;
if (certReqCtxLen > 0) {
XMEMCPY(output + i, certReqCtx, certReqCtxLen);
i += certReqCtxLen;
}
length -= OPAQUE8_LEN + certReqCtxLen;
fragSz -= OPAQUE8_LEN + certReqCtxLen;
/* Certificate list length. */
c32to24(listSz, output + i);
i += CERT_HEADER_SZ;
@ -3978,6 +4019,14 @@ int SendTls13Certificate(WOLFSSL* ssl)
ssl->options.serverState = SERVER_CERT_COMPLETE;
}
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) {
CertReqCtx* ctx = ssl->certReqCtx;
ssl->certReqCtx = ssl->certReqCtx->next;
XFREE(ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
return ret;
}
@ -4344,7 +4393,23 @@ exit_scv:
static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz)
{
return ProcessPeerCerts(ssl, input, inOutIdx, totalSz);
int ret;
ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz);
if (ret != 0)
return ret;
#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.handShakeState == HANDSHAKE_DONE) {
/* reset handshake states */
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
ssl->options.acceptState = TICKET_SENT;
ssl->options.handShakeState = SERVER_FINISHED_COMPLETE;
}
#endif
return 0;
}
#if !defined(NO_RSA) || defined(HAVE_ECC)
@ -4679,6 +4744,8 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
byte* secret;
byte mac[MAX_DIGEST_SIZE];
WOLFSSL_ENTER("DoTls13Finished");
/* check against totalSz */
if (*inOutIdx + size + ssl->keys.padSz > totalSz)
return BUFFER_E;
@ -4724,22 +4791,18 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* Force input exhaustion at ProcessReply by consuming padSz. */
*inOutIdx += size + ssl->keys.padSz;
if (ssl->options.side == WOLFSSL_SERVER_END) {
if (ssl->options.side == WOLFSSL_SERVER_END &&
!ssl->options.handShakeDone) {
/* Setup keys for application data messages from client. */
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
}
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
if (!ssl->options.resuming) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
#endif
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END)
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
#endif
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END) {
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
ssl->options.handShakeState = HANDSHAKE_DONE;
@ -4747,6 +4810,8 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#endif
WOLFSSL_LEAVE("DoTls13Finished", 0);
return 0;
}
#endif /* NO_CERTS */
@ -4767,6 +4832,8 @@ int SendTls13Finished(WOLFSSL* ssl)
int outputSz;
byte* secret;
WOLFSSL_ENTER("SendTls13Finished");
outputSz = MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA;
/* Check buffers are big enough and grow if needed. */
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
@ -4813,12 +4880,6 @@ int SendTls13Finished(WOLFSSL* ssl)
AddSession(ssl); /* just try */
#endif
}
else {
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
@ -4844,7 +4905,8 @@ int SendTls13Finished(WOLFSSL* ssl)
return ret;
}
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.side == WOLFSSL_CLIENT_END &&
!ssl->options.handShakeDone) {
/* Setup keys for application data messages. */
if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
return ret;
@ -4854,6 +4916,23 @@ int SendTls13Finished(WOLFSSL* ssl)
#endif
}
if (ssl->options.resuming) {
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (!ssl->options.resuming) {
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
}
}
#endif
WOLFSSL_LEAVE("SendTls13Finished", ret);
return ret;
}
@ -4872,6 +4951,8 @@ static int SendTls13KeyUpdate(WOLFSSL* ssl)
int outputSz;
word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
WOLFSSL_ENTER("SendTls13KeyUpdate");
outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA;
/* Check buffers are big enough and grow if needed. */
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
@ -4920,6 +5001,8 @@ static int SendTls13KeyUpdate(WOLFSSL* ssl)
if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
return ret;
WOLFSSL_LEAVE("SendTls13KeyUpdate", ret);
return ret;
}
@ -4938,6 +5021,8 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
int ret;
word32 i = *inOutIdx;
WOLFSSL_ENTER("DoTls13KeyUpdate");
/* check against totalSz */
if (OPAQUE8_LEN != totalSz)
return BUFFER_E;
@ -4970,6 +5055,9 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->keys.keyUpdateRespond)
return SendTls13KeyUpdate(ssl);
WOLFSSL_LEAVE("DoTls13KeyUpdate", ret);
return 0;
}
@ -5244,6 +5332,11 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
#ifndef NO_WOLFSSL_CLIENT
case certificate_request:
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
if (ssl->msgsReceived.got_finished)
;
else
#endif
if (ssl->msgsReceived.got_certificate_request) {
WOLFSSL_MSG("Duplicate CertificateRequest received");
return DUPLICATE_MSG_E;
@ -5267,6 +5360,11 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
break;
case finished:
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
if (1) {
}
else
#endif
if (ssl->msgsReceived.got_finished) {
WOLFSSL_MSG("Duplicate Finished received");
return DUPLICATE_MSG_E;
@ -5331,7 +5429,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.handShakeState == HANDSHAKE_DONE &&
type != session_ticket && type != certificate_request &&
type != key_update) {
type != certificate && type != key_update) {
WOLFSSL_MSG("HandShake message after handshake complete");
SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
@ -5766,7 +5864,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
}
#endif /* NO_HANDSHAKE_DONE_CB */
WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS);
WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", SSL_SUCCESS);
return SSL_SUCCESS;
default:
@ -5906,6 +6004,84 @@ int wolfSSL_update_keys(WOLFSSL* ssl)
return ret;
}
#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
/* Allow post-handshake authentication in TLS v1.3 connections.
*
* ctx The SSL/TLS CTX object.
* returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
* 0 on success.
*/
int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
if (ctx->method->side == WOLFSSL_SERVER_END)
return SIDE_ERROR;
ctx->postHandshakeAuth = 1;
return 0;
}
/* Allow post-handshake authentication in TLS v1.3 connection.
*
* ssl The SSL/TLS object.
* returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
* SIDE_ERROR when not a server and 0 on success.
*/
int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl)
{
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
return BAD_FUNC_ARG;
return BAD_FUNC_ARG;
if (ssl->options.side == WOLFSSL_SERVER_END)
return SIDE_ERROR;
ssl->options.postHandshakeAuth = 1;
return 0;
}
/* Request a certificate of the client.
* Can be called any time after handshake completion.
* A maximum of 256 requests can be sent on a connection.
*
* ssl SSL/TLS object.
*/
int wolfSSL_request_certificate(WOLFSSL* ssl)
{
int ret;
CertReqCtx* certReqCtx;
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
return BAD_FUNC_ARG;
if (ssl->options.side == WOLFSSL_CLIENT_END)
return SIDE_ERROR;
if (ssl->options.handShakeState != HANDSHAKE_DONE)
return NOT_READY_ERROR;
if (!ssl->options.postHandshakeAuth)
return POST_HAND_AUTH_ERROR;
certReqCtx = XMALLOC(sizeof(CertReqCtx), ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (certReqCtx == NULL)
return MEMORY_E;
XMEMSET(certReqCtx, 0, sizeof(CertReqCtx));
certReqCtx->next = ssl->certReqCtx;
certReqCtx->len = 1;
if (certReqCtx->next != NULL)
certReqCtx->ctx = certReqCtx->next->ctx + 1;
ssl->certReqCtx = certReqCtx;
ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len);
if (ret == WANT_WRITE)
ret = SSL_ERROR_WANT_WRITE;
else if (ret == 0)
ret = SSL_SUCCESS;
return ret;
}
#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */
/* The server accepting a connection from a client.
* The protocol version is expecting to be TLS v1.3.
* If the client downgrades, and older versions of the protocol are compiled
@ -6042,7 +6218,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
#ifndef NO_CERTS
if (!ssl->options.resuming) {
if (ssl->options.verifyPeer) {
ssl->error = SendTls13CertificateRequest(ssl);
ssl->error = SendTls13CertificateRequest(ssl, NULL, 0);
if (ssl->error != 0) {
WOLFSSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;

View File

@ -253,8 +253,14 @@ void bench_rng(void);
#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \
!defined(HAVE_STACK_SIZE)
#ifdef __cplusplus
extern "C" {
#endif
WOLFSSL_API int wolfSSL_Debugging_ON(void);
WOLFSSL_API void wolfSSL_Debugging_OFF(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
#if !defined(NO_RSA) || !defined(NO_DH) \

View File

@ -307,7 +307,13 @@ int memcb_test(void);
#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \
!defined(OPENSSL_EXTRA) && !defined(HAVE_STACK_SIZE)
int wolfSSL_Debugging_ON(void);
#ifdef __cplusplus
extern "C" {
#endif
WOLFSSL_API int wolfSSL_Debugging_ON();
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
/* General big buffer size for many tests. */

View File

@ -164,10 +164,11 @@ enum wolfSSL_ErrorCodes {
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
/* begin negotiation parameter errors */
UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */
MATCH_SUITE_ERROR = -501, /* can't match cipher suite */
COMPRESSION_ERROR = -502, /* compression mismatch */
KEY_SHARE_ERROR = -503 /* key share mismatch */
UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */
MATCH_SUITE_ERROR = -501, /* can't match cipher suite */
COMPRESSION_ERROR = -502, /* compression mismatch */
KEY_SHARE_ERROR = -503, /* key share mismatch */
POST_HAND_AUTH_ERROR = -504 /* client won't do post-hand auth */
/* end negotiation parameter errors only 10 for now */
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */

View File

@ -1121,6 +1121,7 @@ enum Misc {
MAX_PSK_KEY_LEN = 64, /* max psk key supported */
MIN_PSK_ID_LEN = 6, /* min length of identities */
MIN_PSK_BINDERS_LEN= 33, /* min length of binders */
MAX_TICKET_AGE_SECS= 10, /* maximum ticket age in seconds */
MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4, /* 4 mb file size alloc limit */
@ -1787,6 +1788,9 @@ typedef enum {
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d,
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
TLSX_POST_HANDSHAKE_AUTH = 0x0031,
#endif
#endif
TLSX_RENEGOTIATION_INFO = 0xff01
} TLSX_Type;
@ -2179,6 +2183,9 @@ struct WOLFSSL_CTX {
byte noTicketTls13; /* Server won't create new Ticket */
byte noPskDheKe; /* Don't use (EC)DHE with PSK */
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
byte postHandshakeAuth;/* Post-handshake authentication supported. */
#endif
#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
byte dtlsSctp; /* DTLS-over-SCTP mode */
word16 dtlsMtuSz; /* DTLS MTU size */
@ -2771,6 +2778,10 @@ typedef struct Options {
#endif
word16 keepResources:1; /* Keep resources after handshake */
word16 useClientOrder:1; /* Use client's cipher order */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
word16 postHandshakeAuth:1;/* Client send post_handshake_auth
* extendion. */
#endif
/* need full byte values for this section */
byte processReply; /* nonblocking resume */
@ -3069,6 +3080,15 @@ typedef struct HS_Hashes {
WOLFSSL_LOCAL int NotifyWriteSide(WOLFSSL* ssl, int err);
#endif /* HAVE_WRITE_DUP */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
typedef struct CertReqCtx CertReqCtx;
struct CertReqCtx {
CertReqCtx* next;
byte len;
byte ctx;
};
#endif
/* wolfSSL ssl type */
struct WOLFSSL {
@ -3208,8 +3228,8 @@ struct WOLFSSL {
CallbackFuzzer fuzzerCb; /* for testing with using fuzzer */
void* fuzzerCtx; /* user defined pointer */
#endif
#ifdef WOLFSSL_TLS13
buffer clientCertCtx; /* Certificate context in request */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
CertReqCtx* certReqCtx;
#endif
#ifdef KEEP_PEER_CERT
WOLFSSL_X509 peerCert; /* X509 peer cert */
@ -3452,7 +3472,8 @@ WOLFSSL_LOCAL int SendTls13Certificate(WOLFSSL*);
#endif
WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
#ifdef WOLFSSL_TLS13
WOLFSSL_LOCAL int SendTls13CertificateRequest(WOLFSSL*);
WOLFSSL_LOCAL int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
int reqCtxLen);
#endif
WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*);
WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*);

View File

@ -412,6 +412,9 @@ WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx);
WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx);
WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*);
#endif
WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*);