Merge pull request #956 from dgarske/fix_tls13_async

Fixes for asynchronous TLS 1.3
This commit is contained in:
toddouska
2017-06-13 08:08:34 -07:00
committed by GitHub
11 changed files with 655 additions and 297 deletions

View File

@@ -266,8 +266,11 @@ src_libwolfssl_la_SOURCES += \
src/io.c \
src/keys.c \
src/ssl.c \
src/tls.c \
src/tls13.c
src/tls.c
if BUILD_TLS13
src_libwolfssl_la_SOURCES += src/tls13.c
endif
if BUILD_OCSP
src_libwolfssl_la_SOURCES += src/ocsp.c

View File

@@ -127,21 +127,6 @@ enum processReply {
runProcessingOneMessage
};
/* sub-states for build message */
enum buildMsgState {
BUILD_MSG_BEGIN = 0,
BUILD_MSG_SIZE,
BUILD_MSG_HASH,
BUILD_MSG_VERIFY_MAC,
BUILD_MSG_ENCRYPT,
};
/* sub-states for cipher operations */
enum cipherState {
CIPHER_STATE_BEGIN = 0,
CIPHER_STATE_DO,
CIPHER_STATE_END,
};
/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */
static const byte tls13Downgrade[7] = {
@@ -2919,7 +2904,8 @@ static int TypeHash(int hashAlgo)
}
#if defined(WC_RSA_PSS)
static int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf) {
int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf)
{
switch (hashAlgo) {
#ifdef WOLFSSL_SHA512
case sha512_mac:
@@ -3105,10 +3091,11 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
return ret;
ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf,
key);
if (ret > 0)
if (ret > 0) {
ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType);
if (ret != 0)
ret = VERIFY_CERT_ERROR;
}
}
else
#endif
@@ -3362,7 +3349,9 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
int side, void* ctx)
{
int ret;
#ifdef WOLFSSL_ASYNC_CRYPT
WC_ASYNC_DEV* asyncDev;
#endif
(void)ssl;
(void)pubKeyDer;
(void)pubKeySz;
@@ -3380,18 +3369,23 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer,
pubKeySz, out, outlen, side, ctx);
}
#ifdef WOLFSSL_ASYNC_CRYPT
asyncDev = &otherKey->asyncDev;
#endif
}
else
#endif
{
ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
#ifdef WOLFSSL_ASYNC_CRYPT
asyncDev = &priv_key->asyncDev;
#endif
}
/* Handle async pending response */
#if defined(WOLFSSL_ASYNC_CRYPT)
if (ret == WC_PENDING_E) {
ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev,
WC_ASYNC_FLAG_CALL_AGAIN);
ret = wolfSSL_AsyncPush(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5558,6 +5552,9 @@ int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz)
(void)output;
(void)sz;
if (ssl->hsHashes == NULL)
return BAD_FUNC_ARG;
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx);
@@ -9307,7 +9304,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#ifdef WOLFSSL_ASYNC_CRYPT
/* if async, offset index so this msg will be processed again */
if (ret == WC_PENDING_E) {
if (ret == WC_PENDING_E && *inOutIdx > 0) {
*inOutIdx -= HANDSHAKE_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
@@ -9575,6 +9572,10 @@ static int DtlsMsgDrain(WOLFSSL* ssl)
ssl->keys.dtls_expected_peer_handshake_number++;
ret = DoHandShakeMsgType(ssl, item->msg,
&idx, item->type, item->sz, item->sz);
if (ret == WC_PENDING_E) {
ssl->keys.dtls_expected_peer_handshake_number--;
break;
}
ssl->dtls_rx_msg_list = item->next;
DtlsMsgDelete(item, ssl->heap);
item = ssl->dtls_rx_msg_list;
@@ -9594,10 +9595,24 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
int ret = 0;
WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
/* process any pending DTLS messages - this flow can happen with async */
if (ssl->dtls_rx_msg_list != NULL) {
ret = DtlsMsgDrain(ssl);
if (ret != 0)
return ret;
/* if done processing fragment exit with success */
if (totalSz == *inOutIdx)
return ret;
}
/* parse header */
if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
&size, &fragOffset, &fragSz, totalSz) != 0)
return PARSE_ERROR;
/* check that we have complete fragment */
if (*inOutIdx + fragSz > totalSz)
return INCOMPLETE_DATA;
@@ -10209,7 +10224,7 @@ static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz,
int ret = 0;
#ifdef WOLFSSL_ASYNC_CRYPT
if (asyncOkay && ssl->error == WC_PENDING_E) {
if (ssl->error == WC_PENDING_E) {
ssl->error = 0; /* clear async */
}
#endif
@@ -11956,12 +11971,12 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay)
{
int ret = 0;
BuildMsgArgs* args;
BuildMsgArgs lcl_args;
#ifdef WOLFSSL_ASYNC_CRYPT
BuildMsgArgs* args = (BuildMsgArgs*)ssl->async.args;
args = (BuildMsgArgs*)ssl->async.args;
typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1];
(void)sizeof(args_test);
#else
BuildMsgArgs args[1];
#endif
WOLFSSL_ENTER("BuildMessage");
@@ -11973,7 +11988,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
return BuildTls13Message(ssl, output, outSz, input, inSz, type,
hashOutput, sizeOnly);
hashOutput, sizeOnly, asyncOkay);
}
#endif
@@ -11987,7 +12002,11 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
goto exit_buildmsg;
}
}
else
#endif
{
args = &lcl_args;
}
/* Reset state */
if (ret == WC_NOT_PENDING_E) {
@@ -13189,7 +13208,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
else {
#ifdef WOLFSSL_TLS13
sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz,
application_data, 0, 0);
application_data, 0, 0, 1);
#else
sendSz = BUFFER_ERROR;
#endif
@@ -17921,7 +17940,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
{
ecc_key* peerKey;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_PK_CALLBACKS
/* if callback then use it for shared secret */
#ifdef HAVE_CURVE25519
if (ssl->ecdhCurveOID == ECC_X25519_OID) {
@@ -17933,7 +17952,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
if (ssl->ctx->EccSharedSecretCb != NULL) {
break;
}
#endif
#endif /* HAVE_PK_CALLBACKS */
#ifdef HAVE_CURVE25519
if (ssl->peerX25519KeyPresent) {
@@ -18261,7 +18280,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
break;
}
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_PK_CALLBACKS
/* if callback then use it for shared secret */
if (ssl->ctx->EccSharedSecretCb != NULL) {
break;
@@ -18679,11 +18698,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
{
if (IsEncryptionOn(ssl, 1)) {
ret = BuildMessage(ssl, args->output, args->sendSz,
args->input, args->inputSz, handshake, 1, 0, 1);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E)
goto exit_scke;
#endif
args->input, args->inputSz, handshake, 1, 0, 0);
XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
args->input = NULL; /* make sure its not double free'd on cleanup */

View File

@@ -1439,6 +1439,27 @@ int wolfSSL_CTX_UseAsync(WOLFSSL_CTX* ctx, int devId)
#endif /* WOLFSSL_ASYNC_CRYPT */
/* helpers to get device id and heap */
int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
{
int devId = INVALID_DEVID;
if (ctx != NULL)
devId = ctx->devId;
else if (ssl != NULL)
devId = ssl->devId;
return devId;
}
void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
{
void* heap = NULL;
if (ctx != NULL)
heap = ctx->heap;
else if (ssl != NULL)
heap = ssl->heap;
return heap;
}
#ifdef HAVE_SNI
int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size)
@@ -4260,7 +4281,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff,
long* used, EncryptedInfo* info)
{
int ret = 0;
void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL);
void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
#ifdef WOLFSSL_TLS13
int cnt = 0;
#endif
@@ -4401,8 +4422,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
int ed25519Key = 0;
int rsaKey = 0;
int resetSuites = 0;
void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL);
int devId = ctx ? ctx->devId : ((ssl) ? ssl->devId : INVALID_DEVID);
void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
#else
@@ -4965,7 +4986,7 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
NULL) == 0) {
WOLFSSL_MSG(" Proccessed a CRL");
wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer,
der->length,SSL_FILETYPE_ASN1);
der->length, SSL_FILETYPE_ASN1);
FreeDer(&der);
used += info.consumed;
continue;
@@ -5525,7 +5546,7 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
int ret;
long sz = 0;
XFILE file;
void* heapHint = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL);
void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl);
(void)crl;
(void)heapHint;
@@ -8199,6 +8220,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
return SSL_FATAL_ERROR;
}
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
#ifdef WOLFSSL_DTLS
if (ssl->version.major == DTLS_MAJOR) {
ssl->options.dtls = 1;
@@ -8274,10 +8300,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
if (ssl->options.certOnly)
return SSL_SUCCESS;
#ifdef WOLFSSL_TLS13
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
#endif
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl)) {
@@ -8322,6 +8348,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case FIRST_REPLY_DONE :
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
#ifndef NO_CERTS
if (ssl->options.sendVerify) {
if ( (ssl->error = SendCertificate(ssl)) != 0) {
@@ -8337,6 +8367,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case FIRST_REPLY_FIRST :
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3)
return wolfSSL_connect_TLSv13(ssl);
#endif
if (!ssl->options.resuming) {
if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
@@ -8620,11 +8654,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case ACCEPT_FIRST_REPLY_DONE :
#ifdef WOLFSSL_TLS13
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
return wolfSSL_accept_TLSv13(ssl);
}
#endif
#endif
if ( (ssl->error = SendServerHello(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;
@@ -8634,6 +8668,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case SERVER_HELLO_SENT :
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
return wolfSSL_accept_TLSv13(ssl);
}
#endif
#ifndef NO_CERTS
if (!ssl->options.resuming)
if ( (ssl->error = SendCertificate(ssl)) != 0) {
@@ -8658,6 +8697,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
FALL_THROUGH;
case CERT_STATUS_SENT :
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
return wolfSSL_accept_TLSv13(ssl);
}
#endif
if (!ssl->options.resuming)
if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);

View File

@@ -4775,7 +4775,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
kse->key = key;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Public ECC Key");
WOLFSSL_MSG("Public Curve25519 Key");
WOLFSSL_BUFFER(keyData, dataSize);
#endif
@@ -5130,7 +5130,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Peer ECC Key");
WOLFSSL_MSG("Peer Curve25519 Key");
WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -5835,8 +5835,8 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz)
break;
#elif defined(WOLFSSL_CERT_EXT)
/* decode cert policy */
if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], MAX_CERTPOL_SZ,
input + idx, length) != 0) {
if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb],
MAX_CERTPOL_SZ, input + idx, length) != 0) {
WOLFSSL_MSG("\tCouldn't decode CertPolicy");
return ASN_PARSE_E;
}

View File

@@ -20,7 +20,7 @@
*/
/* Based from Daniel Beer's public domain word. */
/* Based from Daniel Beer's public domain work. */
#ifdef HAVE_CONFIG_H
#include <config.h>

View File

@@ -2672,6 +2672,22 @@ enum asyncState {
TLS_ASYNC_END
};
/* sub-states for build message */
enum buildMsgState {
BUILD_MSG_BEGIN = 0,
BUILD_MSG_SIZE,
BUILD_MSG_HASH,
BUILD_MSG_VERIFY_MAC,
BUILD_MSG_ENCRYPT,
};
/* sub-states for cipher operations */
enum cipherState {
CIPHER_STATE_BEGIN = 0,
CIPHER_STATE_DO,
CIPHER_STATE_END,
};
typedef struct Options {
#ifndef NO_PSK
wc_psk_client_callback client_psk_cb;
@@ -3468,9 +3484,12 @@ WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl);
WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl);
#ifndef NO_CERTS
#ifndef NO_RSA
WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz,
byte* out, word32 sigSz,
enum wc_HashType hashType);
#ifdef WC_RSA_PSS
WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz,
byte* out, word32 sigSz,
enum wc_HashType hashType);
WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf);
#endif
WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl,
byte* verifySig, word32 sigSz,
const byte* plain, word32 plainSz,
@@ -3637,7 +3656,7 @@ WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
#ifdef WOLFSSL_TLS13
int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
int inSz, int type, int hashOutput, int sizeOnly);
int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay);
#endif
WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey);

View File

@@ -1701,6 +1701,10 @@ WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_UseAsync(WOLFSSL*, int devId);
WOLFSSL_API int wolfSSL_CTX_UseAsync(WOLFSSL_CTX*, int devId);
/* helpers to get device id and heap */
WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
/* TLS Extensions */
/* Server Name Indication */

View File

@@ -1803,6 +1803,11 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
ret = wc_InitRng(&rng);
if (ret == 0) {
ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) {
ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_NONE);
}
#endif
if (ret == 0)
ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz);
wc_FreeRng(&rng);
@@ -1824,6 +1829,12 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
/* generate shared secret and return it */
if (ret == 0) {
ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) {
ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
}
#endif
}
wc_ecc_free(&tmpKey);

View File

@@ -32,6 +32,10 @@
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/sha512.h>
#ifdef WOLFSSL_ASYNC_CRYPT
#include <wolfssl/wolfcrypt/async.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -69,6 +73,9 @@ struct ed25519_key {
byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */
byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
WC_ASYNC_DEV asyncDev;
#endif
};