From 984d709db0cae88523ece53c16adbd0b9cae8087 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 21 Dec 2022 15:52:55 +0100 Subject: [PATCH 01/29] dtls 1.3: Stateless ClientHello parsing --- IDE/WIN/user_settings.h | 1 + src/dtls.c | 542 ++++++-- src/dtls13.c | 3 +- src/internal.c | 120 +- src/keys.c | 2737 ++++++++++++++++++++------------------- src/ssl.c | 6 +- src/tls.c | 698 +++++----- src/tls13.c | 140 +- tests/api.c | 167 ++- wolfssl/internal.h | 82 +- wolfssl/test.h | 21 + 11 files changed, 2670 insertions(+), 1847 deletions(-) diff --git a/IDE/WIN/user_settings.h b/IDE/WIN/user_settings.h index 2722854a7..919924e9e 100644 --- a/IDE/WIN/user_settings.h +++ b/IDE/WIN/user_settings.h @@ -14,6 +14,7 @@ #define WC_RSA_PSS #define WOLFSSL_DTLS #define WOLFSSL_DTLS13 +#define WOLFSSL_SEND_HRR_COOKIE #define WOLFSSL_DTLS_CID /* Configurations */ diff --git a/src/dtls.c b/src/dtls.c index 55f6cd8d5..b9c683a3c 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -46,6 +46,8 @@ #include #endif +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + #ifdef WOLFSSL_DTLS void DtlsResetState(WOLFSSL* ssl) @@ -54,11 +56,6 @@ void DtlsResetState(WOLFSSL* ssl) * ClientHello that contains the cookie. Don't gate on IsAtLeastTLSv1_3 * to handle the edge case when the peer wants a lower version. */ -#ifdef WOLFSSL_SEND_HRR_COOKIE - /* Remove cookie so that it will get computed again */ - TLSX_Remove(&ssl->extensions, TLSX_COOKIE, ssl->heap); -#endif - /* Reset DTLS window */ #ifdef WOLFSSL_DTLS13 w64Zero(&ssl->dtls13Epochs[0].nextSeqNumber); @@ -79,10 +76,10 @@ void DtlsResetState(WOLFSSL* ssl) ssl->msgsReceived.got_client_hello = 0; ssl->keys.dtls_handshake_number = 0; ssl->keys.dtls_expected_peer_handshake_number = 0; - ssl->options.clientState = 0; - XMEMSET(ssl->keys.peerSeq->window, 0, sizeof(ssl->keys.peerSeq->window)); - XMEMSET(ssl->keys.peerSeq->prevWindow, 0, - sizeof(ssl->keys.peerSeq->prevWindow)); + XMEMSET(ssl->keys.peerSeq, 0, sizeof(ssl->keys.peerSeq)); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->options.tls1_3 = 0; } #if !defined(NO_WOLFSSL_SERVER) @@ -114,7 +111,11 @@ typedef struct WolfSSL_CH { WolfSSL_ConstVector cipherSuite; WolfSSL_ConstVector compression; WolfSSL_ConstVector extension; + const byte* msg; word32 length; + /* Store the DTLS 1.2 cookie since we can just compute it once in dtls.c */ + byte dtls12cookie[DTLS_COOKIE_SZ]; + byte dtls12cookieSet:1; } WolfSSL_CH; static int ReadVector8(const byte* input, WolfSSL_ConstVector* v) @@ -133,45 +134,82 @@ static int ReadVector16(const byte* input, WolfSSL_ConstVector* v) return v->size + OPAQUE16_LEN; } -static int CreateDtlsCookie(WOLFSSL* ssl, const WolfSSL_CH* ch, byte* cookie) +static int CreateDtls12Cookie(const WOLFSSL* ssl, const WolfSSL_CH* ch, + byte* cookie) { - Hmac cookieHmac; int ret; - + Hmac cookieHmac; ret = wc_HmacInit(&cookieHmac, ssl->heap, ssl->devId); - if (ret != 0) - return ret; - ret = wc_HmacSetKey(&cookieHmac, DTLS_COOKIE_TYPE, - ssl->buffers.dtlsCookieSecret.buffer, - ssl->buffers.dtlsCookieSecret.length); - if (ret != 0) - goto out; - ret = wc_HmacUpdate(&cookieHmac, (const byte*)ssl->buffers.dtlsCtx.peer.sa, - ssl->buffers.dtlsCtx.peer.sz); - if (ret != 0) - goto out; - ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->pv, OPAQUE16_LEN); - if (ret != 0) - goto out; - ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->random, RAN_LEN); - if (ret != 0) - goto out; - ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->sessionId.elements, - ch->sessionId.size); - if (ret != 0) - goto out; - ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->cipherSuite.elements, - ch->cipherSuite.size); - if (ret != 0) - goto out; - ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->compression.elements, - ch->compression.size); - if (ret != 0) - goto out; - ret = wc_HmacFinal(&cookieHmac, cookie); + if (ret == 0) { + ret = wc_HmacSetKey(&cookieHmac, DTLS_COOKIE_TYPE, + ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + if (ret == 0) { + ret = wc_HmacUpdate(&cookieHmac, + (const byte*)ssl->buffers.dtlsCtx.peer.sa, + ssl->buffers.dtlsCtx.peer.sz); + } + if (ret == 0) + ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->pv, OPAQUE16_LEN); + if (ret == 0) + ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->random, RAN_LEN); + if (ret == 0) { + ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->sessionId.elements, + ch->sessionId.size); + } + if (ret == 0) { + ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->cipherSuite.elements, + ch->cipherSuite.size); + } + if (ret == 0) { + ret = wc_HmacUpdate(&cookieHmac, (byte*)ch->compression.elements, + ch->compression.size); + } + if (ret == 0) + ret = wc_HmacFinal(&cookieHmac, cookie); + wc_HmacFree(&cookieHmac); + } -out: - wc_HmacFree(&cookieHmac); + return ret; +} + +static int CheckDtlsCookie(const WOLFSSL* ssl, WolfSSL_CH* ch, + byte isTls13, byte* cookieGood) +{ + int ret = 0; + + (void)isTls13; + + *cookieGood = 0; +#ifdef WOLFSSL_DTLS13 + if (isTls13) { + word16 len; + if (ch->cookie.size < OPAQUE16_LEN + 1) + return BUFFER_E; + ato16(ch->cookie.elements, &len); + if (ch->cookie.size - OPAQUE16_LEN != len) + return BUFFER_E; + ret = TlsCheckCookie(ssl, ch->cookie.elements + OPAQUE16_LEN, + ch->cookie.size - OPAQUE16_LEN); + if (ret < 0 && ret != HRR_COOKIE_ERROR) + return ret; + *cookieGood = ret > 0; + ret = 0; + } + else +#endif + { + if (ch->cookie.size != DTLS_COOKIE_SZ) + return 0; + if (!ch->dtls12cookieSet) { + ret = CreateDtls12Cookie(ssl, ch, ch->dtls12cookie); + if (ret != 0) + return ret; + ch->dtls12cookieSet = 1; + } + *cookieGood = ConstantCompare(ch->cookie.elements, ch->dtls12cookie, + DTLS_COOKIE_SZ) == 0; + } return ret; } @@ -183,6 +221,7 @@ static int ParseClientHello(const byte* input, word32 helloSz, WolfSSL_CH* ch) if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; + ch->msg = input - DTLS_HANDSHAKE_HEADER_SZ; ch->pv = (ProtocolVersion*)(input + idx); idx += OPAQUE16_LEN; ch->random = (byte*)(input + idx); @@ -202,12 +241,12 @@ static int ParseClientHello(const byte* input, word32 helloSz, WolfSSL_CH* ch) idx += ReadVector16(input + idx, &ch->extension); if (idx > helloSz) return BUFFER_ERROR; - ch->length = idx; + ch->length = idx + DTLS_HANDSHAKE_HEADER_SZ; return 0; } -#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME -#ifdef HAVE_SESSION_TICKET +#if (defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) && defined(HAVE_SESSION_TICKET)) \ + || defined(WOLFSSL_DTLS13) static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, WolfSSL_ConstVector exts) { @@ -232,16 +271,18 @@ static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, } return 0; } +#endif -static int TlsTicketIsValid(WOLFSSL* ssl, WolfSSL_ConstVector exts, - byte* isValid) +#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME +#ifdef HAVE_SESSION_TICKET +static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, + PskInfo* pskInfo) { WolfSSL_ConstVector tlsxSessionTicket; byte tempTicket[SESSION_TICKET_LEN]; InternalTicket* it; int ret; - *isValid = 0; ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts); if (ret != 0) return ret; @@ -250,23 +291,28 @@ static int TlsTicketIsValid(WOLFSSL* ssl, WolfSSL_ConstVector exts, if (tlsxSessionTicket.size > SESSION_TICKET_LEN) return 0; XMEMCPY(tempTicket, tlsxSessionTicket.elements, tlsxSessionTicket.size); - ret = DoDecryptTicket(ssl, tempTicket, (word32)tlsxSessionTicket.size, &it); + ret = DoDecryptTicket((WOLFSSL*)ssl, tempTicket, + (word32)tlsxSessionTicket.size, &it); if (ret != WOLFSSL_TICKET_RET_OK && ret != WOLFSSL_TICKET_RET_CREATE) return 0; + /* Store info for later */ + pskInfo->pv = it->pv; + pskInfo->cipherSuite0 = it->suite[0]; + pskInfo->cipherSuite = it->suite[1]; + ato16(it->namedGroup, &pskInfo->namedGroup); + ForceZero(it, sizeof(InternalTicket)); - *isValid = 1; + pskInfo->isValid = 1; return 0; } #endif /* HAVE_SESSION_TICKET */ -static int TlsSessionIdIsValid(WOLFSSL* ssl, WolfSSL_ConstVector sessionID, - byte* isValid) +static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID, + PskInfo* pskInfo) { WOLFSSL_SESSION* sess; word32 sessRow; int ret; - - *isValid = 0; if (ssl->options.sessionCacheOff) return 0; if (sessionID.size != ID_LEN) @@ -277,9 +323,16 @@ static int TlsSessionIdIsValid(WOLFSSL* ssl, WolfSSL_ConstVector sessionID, if (ssl->ctx->get_sess_cb != NULL) { int unused; sess = - ssl->ctx->get_sess_cb(ssl, sessionID.elements, ID_LEN, &unused); + ssl->ctx->get_sess_cb((WOLFSSL*)ssl, sessionID.elements, ID_LEN, + &unused); if (sess != NULL) { - *isValid = 1; + /* Store info for later */ + pskInfo->pv = sess->version; + pskInfo->cipherSuite0 = sess->cipherSuite0; + pskInfo->cipherSuite = sess->cipherSuite; + pskInfo->namedGroup = sess->namedGroup; + + pskInfo->isValid = 1; wolfSSL_FreeSession(ssl->ctx, sess); return 0; } @@ -290,60 +343,385 @@ static int TlsSessionIdIsValid(WOLFSSL* ssl, WolfSSL_ConstVector sessionID, #endif ret = TlsSessionCacheGetAndLock(sessionID.elements, &sess, &sessRow, 1); if (ret == 0 && sess != NULL) { - *isValid = 1; + /* Store info for later */ + pskInfo->pv = sess->version; + pskInfo->cipherSuite0 = sess->cipherSuite0; + pskInfo->cipherSuite = sess->cipherSuite; + pskInfo->namedGroup = sess->namedGroup; + + pskInfo->isValid = 1; TlsSessionCacheUnlockRow(sessRow); } return 0; } -static int TlsResumptionIsValid(WOLFSSL* ssl, WolfSSL_CH* ch, byte* isValid) +static int TlsResumptionIsValid(const WOLFSSL* ssl, WolfSSL_CH* ch, + PskInfo* pskInfo) { int ret; - *isValid = 0; #ifdef HAVE_SESSION_TICKET - ret = TlsTicketIsValid(ssl, ch->extension, isValid); + ret = TlsTicketIsValid(ssl, ch->extension, pskInfo); if (ret != 0) return ret; - if (*isValid) + if (pskInfo->isValid) return 0; #endif /* HAVE_SESSION_TICKET */ - ret = TlsSessionIdIsValid(ssl, ch->sessionId, isValid); + ret = TlsSessionIdIsValid(ssl, ch->sessionId, pskInfo); return ret; } #endif /* WOLFSSL_DTLS_NO_HVR_ON_RESUME */ -int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32* inOutIdx, - word32 helloSz, byte* process) +#ifdef WOLFSSL_DTLS13 +static int TlsCheckSupportedVersion(const WOLFSSL* ssl, + WolfSSL_CH* ch, byte *isTls13, PskInfo* pskInfo) +{ + WolfSSL_ConstVector tlsxSupportedVersions; + int ret; + ProtocolVersion pv = ssl->version; + + ret = TlsxFindByType(&tlsxSupportedVersions, TLSX_SUPPORTED_VERSIONS, + ch->extension); + if (ret != 0) + return ret; + if (tlsxSupportedVersions.size == 0) { + *isTls13 = 0; + return 0; + } + ret = TLSX_SupportedVersions_Parse(ssl, tlsxSupportedVersions.elements, + tlsxSupportedVersions.size, client_hello, &pv, NULL, NULL); + if (ret != 0) + return ret; + if (pskInfo->isValid && (pskInfo->pv.major != pv.major || + pskInfo->pv.minor != pv.minor)) + return VERSION_ERROR; + if (IsAtLeastTLSv1_3(pv)) + *isTls13 = 1; + else + *isTls13 = 0; + + return 0; +} + +static int CopyExtensions(TLSX* src, TLSX** dst, void* heap) +{ + /* Copy the following extensions + * * SupportedCurves */ + TLSX* extension; + int ret; + + extension = TLSX_Find(src, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) { + SupportedCurve* curve; + curve = (SupportedCurve*)extension->data; + for (curve = (SupportedCurve*)extension->data; curve != NULL; + curve = curve->next) { + ret = TLSX_UseSupportedCurve(dst, curve->name, heap); + if (ret != WOLFSSL_SUCCESS) + return MEMORY_E; + } + } + + return 0; +} +#endif + +static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, + PskInfo* pskInfo) +{ + int ret; + (void)isTls13; + (void)pskInfo; +#ifdef WOLFSSL_DTLS13 + if (isTls13) { +#ifdef WOLFSSL_SEND_HRR_COOKIE + if (ch->cookie.size == 0) { + TLSX* parsedExts = NULL; + WolfSSL_ConstVector tlsx; + Suites suites; + word16 len; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + byte haveKS = 0; + byte usePSK = 0; + byte doKE = 0; +#endif + CipherSuite cs; + CipherSpecs specs; + + XMEMSET(&cs, 0, sizeof(cs)); + XMEMSET(&specs, 0, sizeof(specs)); + + /* We need to echo the session ID sent by the client */ + if (ch->sessionId.size > ID_LEN) { + /* Too large. We can't echo this. */ + ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); + } + + /* Hashes are reset in SendTls13ServerHello when sending a HRR */ + ret = Dtls13HashHandshake((WOLFSSL*)ssl, ch->msg, ch->length); + if (ret != 0) + goto dtls13_cleanup; + + /* Populate the suites struct to find a common ciphersuite */ + XMEMSET(&suites, 0, sizeof(suites)); + suites.suiteSz = ch->cipherSuite.size; + if ((suites.suiteSz % 2) != 0) + ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); + if (suites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + XMEMCPY(suites.suites, ch->cipherSuite.elements, suites.suiteSz); + + /* Populate extensions */ + + /* Supported versions always need to be present. Has to appear after + * key share as that is the order we reconstruct it in + * RestartHandshakeHashWithCookie. */ + ret = TLSX_Push(&parsedExts, + TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); + if (ret != 0) + goto dtls13_cleanup; + /* Set that this is a response extension */ + parsedExts->resp = 1; + + ret = CopyExtensions(ssl->extensions, &parsedExts, ssl->heap); + if (ret != 0) + goto dtls13_cleanup; + + /* Signature algs */ + ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size > OPAQUE16_LEN) { + ato16(tlsx.elements, &len); + if (len != tlsx.size - OPAQUE16_LEN) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + if ((len % 2) != 0) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + suites.hashSigAlgoSz = len; + XMEMCPY(suites.hashSigAlgo, tlsx.elements + OPAQUE16_LEN, + len); + } + + /* Supported groups */ + ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, + tlsx.size, 1, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; + } + + /* Key share */ + ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, + tlsx.size, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + haveKS = 1; +#endif + } + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Pre-shared key */ + ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + /* Let's just assume that the binders are correct here. We will + * actually verify this in the stateful part of the processing + * and if they don't match we will error out there anyway. */ + byte modes; + + ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size == 0) + ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); + ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, + client_hello, &modes); + if (ret != 0) + goto dtls13_cleanup; + if ((modes & (1 << PSK_DHE_KE)) && !ssl->options.noPskDheKe) { + if (!haveKS) + ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); + doKE = 1; + } + else { + if ((modes & (1 << PSK_KE)) == 0) + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + } + } +#endif + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (usePSK) { + if (pskInfo->isValid) { + cs.cipherSuite0 = pskInfo->cipherSuite0; + cs.cipherSuite = pskInfo->cipherSuite; + } + else { + /* Only support the default ciphersuite for PSK */ + cs.cipherSuite0 = TLS13_BYTE; + cs.cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + } + + if (doKE) { + byte searched = 0; + ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE, + &searched); + if (ret != 0) + goto dtls13_cleanup; + if (cs.clientKSE == NULL && searched) + cs.doHelloRetry = 1; + } + } + else +#endif + { + ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); + if (ret < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + SendAlert((WOLFSSL*)ssl, alert_fatal, handshake_failure); + goto dtls13_cleanup; + } + } + if (cs.doHelloRetry) { + ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; + } + + /* Need to remove the keyshare ext if we are not doing PSK and we + * found a common group. */ + if (cs.clientKSE != NULL +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + && !usePSK +#endif + ) + { + TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); + } + + { + WOLFSSL* nonConstSSL = (WOLFSSL*)ssl; + TLSX* sslExts = nonConstSSL->extensions; + + /* This is required to correctly generate the hash */ + ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, + cs.cipherSuite, &nonConstSSL->specs, NULL); + if (ret != 0) + goto dtls13_cleanup; + nonConstSSL->options.tls = 1; + nonConstSSL->options.tls1_1 = 1; + nonConstSSL->options.tls1_3 = 1; + + XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, + ch->sessionId.size); + nonConstSSL->session->sessionIDSz = ch->sessionId.size; + nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; + nonConstSSL->options.cipherSuite = cs.cipherSuite; + nonConstSSL->extensions = parsedExts; + + + ret = SendTls13ServerHello(nonConstSSL, hello_retry_request); + + InitCipherSpecs(&nonConstSSL->specs); + + nonConstSSL->session->sessionIDSz = 0; + nonConstSSL->options.cipherSuite0 = 0; + nonConstSSL->options.cipherSuite = 0; + nonConstSSL->extensions = sslExts; + + nonConstSSL->options.tls = 0; + nonConstSSL->options.tls1_1 = 0; + nonConstSSL->options.tls1_3 = 0; + } +dtls13_cleanup: + TLSX_FreeAll(parsedExts, ssl->heap); + } + else + ret = SendAlert((WOLFSSL*)ssl, alert_fatal, illegal_parameter); +#else +#error "WOLFSSL_SEND_HRR_COOKIE has to be defined to use DTLS 1.3 server" +#endif + } + else +#endif + { + if (!ch->dtls12cookieSet) { + ret = CreateDtls12Cookie(ssl, ch, ch->dtls12cookie); + if (ret != 0) + return ret; + ch->dtls12cookieSet = 1; + } + ret = SendHelloVerifyRequest((WOLFSSL*)ssl, ch->dtls12cookie, + DTLS_COOKIE_SZ); + } + return ret; +} + +int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 helloSz) { - byte cookie[DTLS_COOKIE_SZ]; int ret; WolfSSL_CH ch; + byte isTls13 = 0; + PskInfo pskInfo; - *process = 1; + XMEMSET(&pskInfo, 0, sizeof(pskInfo)); + XMEMSET(&ch, 0, sizeof(ch)); + + ssl->options.dtlsStateful = 0; ret = ParseClientHello(input + *inOutIdx, helloSz, &ch); if (ret != 0) return ret; #ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME - { - byte isValid = 0; - ret = TlsResumptionIsValid(ssl, &ch, &isValid); - if (ret != 0) - return ret; - if (isValid) - return 0; + ret = TlsResumptionIsValid(ssl, &ch, &pskInfo); + if (ret != 0) + return ret; + if (pskInfo.isValid) { + ssl->options.dtlsStateful = 1; + return 0; } #endif /* WOLFSSL_DTLS_NO_HVR_ON_RESUME */ - ret = CreateDtlsCookie(ssl, &ch, cookie); - if (ret != 0) - return ret; - if (ch.cookie.size != DTLS_COOKIE_SZ || - XMEMCMP(ch.cookie.elements, cookie, DTLS_COOKIE_SZ) != 0) { - *process = 0; - ret = SendHelloVerifyRequest(ssl, cookie, DTLS_COOKIE_SZ); +#ifdef WOLFSSL_DTLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = TlsCheckSupportedVersion(ssl, &ch, &isTls13, &pskInfo); + if (ret != 0) + return ret; + if (isTls13) { + ret = TlsxFindByType(&ch.cookie, TLSX_COOKIE, ch.extension); + if (ret != 0) + return ret; + } + } +#endif + + if (ch.cookie.size == 0) { + ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); + } + else { + byte cookieGood; + ret = CheckDtlsCookie(ssl, &ch, isTls13, &cookieGood); + if (ret != 0) + return ret; + if (!cookieGood) + ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); + else + ssl->options.dtlsStateful = 1; } return ret; diff --git a/src/dtls13.c b/src/dtls13.c index d7216b5a3..73944a716 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -330,7 +330,8 @@ static byte Dtls13RtxMsgNeedsAck(WOLFSSL* ssl, enum HandShakeType hs) static void Dtls13MsgWasProcessed(WOLFSSL* ssl, enum HandShakeType hs) { - ssl->keys.dtls_expected_peer_handshake_number++; + if (ssl->options.dtlsStateful) + ssl->keys.dtls_expected_peer_handshake_number++; /* we need to send ACKs on the last message of a flight that needs explicit acknowledgment */ diff --git a/src/internal.c b/src/internal.c index f843345e7..8f1564cc4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -558,7 +558,7 @@ int IsDtlsNotSctpMode(WOLFSSL* ssl) /* Secure Real-time Transport Protocol */ /* If SRTP is not enabled returns the state of the dtls option. * If SRTP is enabled returns dtls && !dtlsSrtpProfiles. */ -static WC_INLINE int IsDtlsNotSrtpMode(WOLFSSL* ssl) +int IsDtlsNotSrtpMode(WOLFSSL* ssl) { #ifdef WOLFSSL_SRTP return ssl->options.dtls && !ssl->dtlsSrtpProfiles; @@ -15663,8 +15663,6 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* above checks handshake state */ /* hello_request not hashed */ - /* Also, skip hashing the client_hello message here for DTLS. It will be - * hashed later if the DTLS cookie is correct. */ if (type != hello_request #ifdef WOLFSSL_ASYNC_CRYPT && ssl->error != WC_PENDING_E @@ -20451,7 +20449,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, #endif /* !NO_OLD_TLS && !WOLFSSL_AEAD_ONLY */ #if !defined(NO_MD5) && !defined(NO_OLD_TLS) -static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) +static int BuildMD5_CertVerify(const WOLFSSL* ssl, byte* digest) { int ret; byte md5_result[WC_MD5_DIGEST_SIZE]; @@ -20495,7 +20493,7 @@ static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ defined(WOLFSSL_ALLOW_TLS_SHA1)) -static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +static int BuildSHA_CertVerify(const WOLFSSL* ssl, byte* digest) { int ret; byte sha_result[WC_SHA_DIGEST_SIZE]; @@ -20537,7 +20535,7 @@ static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) } #endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */ -int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +int BuildCertHashes(const WOLFSSL* ssl, Hashes* hashes) { int ret = 0; @@ -22879,7 +22877,11 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type) ssl->alert_history.last_tx.code = type; ssl->alert_history.last_tx.level = severity; if (severity == alert_fatal) { - ssl->options.isClosed = 1; /* Don't send close_notify */ +#ifdef WOLFSSL_DTLS + /* Mark as closed in dtls only once we enter stateful mode. */ + if (!ssl->options.dtls || ssl->options.dtlsStateful) +#endif + ssl->options.isClosed = 1; /* Don't send close_notify */ } /* send encrypted alert if encryption is on - can be a rehandshake over @@ -27040,17 +27042,13 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, /* Make sure client setup is valid for this suite, true on success */ - int VerifyClientSuite(WOLFSSL* ssl) + int VerifyClientSuite(word16 havePSK, byte cipherSuite0, byte cipherSuite) { - #ifndef NO_PSK - int havePSK = ssl->options.havePSK; - #endif - byte first = ssl->options.cipherSuite0; - byte second = ssl->options.cipherSuite; + (void)havePSK; WOLFSSL_ENTER("VerifyClientSuite"); - if (CipherRequires(first, second, REQUIRES_PSK)) { + if (CipherRequires(cipherSuite0, cipherSuite, REQUIRES_PSK)) { WOLFSSL_MSG("Requires PSK"); #ifndef NO_PSK if (havePSK == 0) @@ -32546,7 +32544,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * Returns 1 for valid server suite or 0 if not found * For asynchronous this can return WC_PENDING_E */ - static int VerifyServerSuite(WOLFSSL* ssl, const Suites* suites, word16 idx) + static int VerifyServerSuite(WOLFSSL* ssl, const Suites* suites, word16 idx, + CipherSuite* cs, TLSX* extensions) { #ifndef NO_PSK int havePSK = ssl->options.havePSK; @@ -32630,7 +32629,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES) - if (!TLSX_ValidateSupportedCurves(ssl, first, second)) { + if (!TLSX_ValidateSupportedCurves(ssl, first, second, cs)) { WOLFSSL_MSG("Don't have matching curves"); return 0; } @@ -32640,25 +32639,23 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.side == WOLFSSL_SERVER_END) { #ifdef HAVE_SUPPORTED_CURVES - int doHelloRetry = 0; - /* Try to establish a key share. */ - int ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry); + byte searched = 0; + int ret = TLSX_KeyShare_Choose(ssl, extensions, &cs->clientKSE, + &searched); if (ret == MEMORY_E) { - WOLFSSL_MSG("TLSX_KeyShare_Establish() failed in " + WOLFSSL_MSG("TLSX_KeyShare_Choose() failed in " "VerifyServerSuite() with MEMORY_E"); return 0; } - if (doHelloRetry) { - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; - } + if (cs->clientKSE == NULL && searched) + cs->doHelloRetry = 1; #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) return ret; #endif - if (!doHelloRetry && ret != 0) { + if (!cs->doHelloRetry && ret != 0) return 0; /* not found */ - } #endif /* HAVE_SUPPORTED_CURVES */ } else if (first == TLS13_BYTE || (first == ECC_BYTE && @@ -32672,26 +32669,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return 1; } - static int CompareSuites(WOLFSSL* ssl, const Suites* suites, - Suites* peerSuites, word16 i, word16 j) + static int CompareSuites(const WOLFSSL* ssl, const Suites* suites, + Suites* peerSuites, word16 i, word16 j, + CipherSuite* cs, TLSX* extensions) { if (suites->suites[i] == peerSuites->suites[j] && suites->suites[i+1] == peerSuites->suites[j+1] ) { - int ret = VerifyServerSuite(ssl, suites, i); + int ret = VerifyServerSuite(ssl, suites, i, cs, extensions); if (ret < 0) { return ret; } if (ret) { WOLFSSL_MSG("Verified suite validity"); - ssl->options.cipherSuite0 = suites->suites[i]; - ssl->options.cipherSuite = suites->suites[i+1]; - ret = SetCipherSpecs(ssl); - if (ret == 0) { - ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); - } - return ret; + cs->cipherSuite0 = suites->suites[i]; + cs->cipherSuite = suites->suites[i+1]; + return 0; } else { WOLFSSL_MSG("Could not verify suite validity, continue"); @@ -32701,7 +32694,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return MATCH_SUITE_ERROR; } - int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + int MatchSuite_ex(const WOLFSSL* ssl, Suites* peerSuites, CipherSuite* cs, + TLSX* extensions) { int ret; word16 i, j; @@ -32720,7 +32714,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Server order */ for (i = 0; i < suites->suiteSz; i += 2) { for (j = 0; j < peerSuites->suiteSz; j += 2) { - ret = CompareSuites(ssl, suites, peerSuites, i, j); + ret = CompareSuites(ssl, suites, peerSuites, i, j, cs, extensions); if (ret != MATCH_SUITE_ERROR) return ret; } @@ -32730,7 +32724,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Client order */ for (j = 0; j < peerSuites->suiteSz; j += 2) { for (i = 0; i < suites->suiteSz; i += 2) { - ret = CompareSuites(ssl, suites, peerSuites, i, j); + ret = CompareSuites(ssl, suites, peerSuites, i, j, cs, extensions); if (ret != MATCH_SUITE_ERROR) return ret; } @@ -32739,6 +32733,46 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_ERROR_VERBOSE(MATCH_SUITE_ERROR); return MATCH_SUITE_ERROR; + + } + + int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + { + int ret; + CipherSuite cs; + + XMEMSET(&cs, 0, sizeof(cs)); + + ret = MatchSuite_ex(ssl, peerSuites, &cs, ssl->extensions); + if (ret != 0) + return ret; + + ssl->options.cipherSuite0 = cs.cipherSuite0; + ssl->options.cipherSuite = cs.cipherSuite; + ssl->ecdhCurveOID = cs.ecdhCurveOID; + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + peerSuites->hashSigAlgoSz); + if (ret != 0) + return ret; + + if (cs.doHelloRetry) { + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions); + } + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END) { + ret = TLSX_KeyShare_Setup(ssl, cs.clientKSE); + if (ret != 0) + return ret; + } +#endif + return ret; } #ifdef OLD_HELLO_ALLOWED @@ -33107,6 +33141,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* do not change state in the SSL object before the next region of code * to be able to statelessly compute a DTLS cookie */ #ifdef WOLFSSL_DTLS + /* Update the ssl->options.dtlsStateful setting `if` statement in + * wolfSSL_accept when changing this one. */ if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl)) { byte process = 0; if (((ssl->keys.dtls_sequence_number_hi == ssl->keys.curSeq_hi && @@ -33121,14 +33157,14 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * Client Hello. */ ssl->keys.dtls_handshake_number = ssl->keys.dtls_peer_handshake_number; - ret = DoClientHelloStateless(ssl, input, inOutIdx, helloSz, - &process); - if (ret != 0 || !process) { + ret = DoClientHelloStateless(ssl, input, inOutIdx, helloSz); + if (ret != 0 || !ssl->options.dtlsStateful) { *inOutIdx += helloSz; DtlsResetState(ssl); return ret; } } + ssl->options.dtlsStateful = 1; #endif /* WOLFSSL_DTLS */ /* protocol version, random and session id length check */ diff --git a/src/keys.c b/src/keys.c index f9da104e0..e4a579602 100644 --- a/src/keys.c +++ b/src/keys.c @@ -44,10 +44,81 @@ int SetCipherSpecs(WOLFSSL* ssl) { + int ret = SetCipherSpecs_ex(ssl->options.side, ssl->options.cipherSuite0, + ssl->options.cipherSuite, &ssl->specs, + &ssl->options); + if (ret == 0) { + /* set TLS if it hasn't been turned off */ + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor >= TLSv1_MINOR) { + #ifndef NO_TLS + ssl->options.tls = 1; + #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + #if !defined(WOLFSSL_RENESAS_SCEPROTECT) && \ + !defined(WOLFSSL_RENESAS_TSIP_TLS) + ssl->hmac = TLS_hmac; + #else + ssl->hmac = Renesas_cmn_TLS_hmac; + #endif + #endif + if (ssl->version.minor >= TLSv1_1_MINOR) { + ssl->options.tls1_1 = 1; + if (ssl->version.minor >= TLSv1_3_MINOR) + ssl->options.tls1_3 = 1; + } + #endif + } + + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block) + ssl->options.encThenMac = 0; + #endif + + #if defined(WOLFSSL_DTLS) + if (ssl->options.dtls && ssl->version.major == DTLS_MAJOR) { + #ifndef WOLFSSL_AEAD_ONLY + #if !defined(WOLFSSL_RENESAS_SCEPROTECT) && \ + !defined(WOLFSSL_RENESAS_TSIP_TLS) + ssl->hmac = TLS_hmac; + #else + ssl->hmac = Renesas_cmn_TLS_hmac; + #endif + #endif + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; /* DTLS 1.0 == TLS 1.1 */ + #ifdef WOLFSSL_DTLS13 + if (ssl->version.minor <= DTLSv1_3_MINOR) + ssl->options.tls1_3 = 1; + #endif + } + #endif + } + return ret; +} + +/** + * + * @param side [in] WOLFSSL_SERVER_END or WOLFSSL_CLIENT_END + * @param cipherSuite0 [in] + * @param cipherSuite [in] + * @param specs [out] CipherSpecs + * @param opts [in/out] Options can be NULL + * @return + */ +int SetCipherSpecs_ex(word16 side, byte cipherSuite0, byte cipherSuite, + CipherSpecs* specs, Options* opts) +{ + word16 havePSK = 0; + (void)havePSK; + (void)side; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (opts != NULL) + havePSK = opts->havePSK; +#endif #ifndef NO_WOLFSSL_CLIENT - if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (side == WOLFSSL_CLIENT_END) { /* server side verified before SetCipherSpecs call */ - if (VerifyClientSuite(ssl) != 1) { + if (VerifyClientSuite(havePSK, cipherSuite0, cipherSuite) != 1) { WOLFSSL_MSG("SetCipherSpecs() client has an unusable suite"); WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_SUITE); return UNSUPPORTED_SUITE; @@ -56,179 +127,191 @@ int SetCipherSpecs(WOLFSSL* ssl) #endif /* NO_WOLFSSL_CLIENT */ /* Chacha extensions, 0xcc */ - if (ssl->options.cipherSuite0 == CHACHA_BYTE) { + if (cipherSuite0 == CHACHA_BYTE) { - switch (ssl->options.cipherSuite) { + switch (cipherSuite) { #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 1; /* use old poly1305 padding */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 1; /* use old poly1305 padding */ break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 1; /* use old poly1305 padding */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 1; /* use old poly1305 padding */ break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 1; /* use old poly1305 padding */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 1; /* use old poly1305 padding */ break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 0; /* use recent padding RFC */ break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 0; /* use recent padding RFC */ break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 0; /* use recent padding RFC */ break; #endif #ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) { + opts->oldPoly = 0; /* use recent padding RFC */ + opts->usingPSK_cipher = 1; + } break; #endif #ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecdhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecdhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) { + opts->oldPoly = 0; /* use recent padding RFC */ + opts->usingPSK_cipher = 1; + } break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) { + opts->oldPoly = 0; /* use recent padding RFC */ + opts->usingPSK_cipher = 1; + } break; #endif default: @@ -238,81 +321,81 @@ int SetCipherSpecs(WOLFSSL* ssl) } /* ECC extensions, AES-CCM or TLS 1.3 Integrity-only */ - if (ssl->options.cipherSuite0 == ECC_BYTE) { + if (cipherSuite0 == ECC_BYTE) { - switch (ssl->options.cipherSuite) { + switch (cipherSuite) { #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_triple_des; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = DES3_KEY_SIZE; + specs->block_size = DES_BLOCK_SIZE; /* DES_IV_SIZE is incorrectly 16 in FIPS v2. It should be 8, same as the * block size. */ #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) - ssl->specs.iv_size = DES_BLOCK_SIZE; + specs->iv_size = DES_BLOCK_SIZE; #else - ssl->specs.iv_size = DES_IV_SIZE; + specs->iv_size = DES_IV_SIZE; #endif break; @@ -320,107 +403,111 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA case TLS_ECDHE_RSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; + specs->bulk_cipher_algorithm = wolfssl_rc4; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = RC4_KEY_SIZE; + specs->iv_size = 0; + specs->block_size = 0; break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 case TLS_ECDHE_PSK_WITH_NULL_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecdhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha256_mac; + specs->kea = ecdhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecdhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = ecdhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif @@ -431,54 +518,54 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_triple_des; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = DES3_KEY_SIZE; + specs->block_size = DES_BLOCK_SIZE; #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) - ssl->specs.iv_size = DES_BLOCK_SIZE; + specs->iv_size = DES_BLOCK_SIZE; #else - ssl->specs.iv_size = DES_IV_SIZE; + specs->iv_size = DES_IV_SIZE; #endif break; @@ -486,158 +573,158 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; + specs->bulk_cipher_algorithm = wolfssl_rc4; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = RC4_KEY_SIZE; + specs->iv_size = 0; + specs->block_size = 0; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM case TLS_ECDHE_ECDSA_WITH_AES_128_CCM : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_16_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA case TLS_ECDHE_ECDSA_WITH_NULL_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; break; #endif @@ -648,105 +735,105 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_128_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_128_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_256_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_256_KEY_SIZE; + specs->iv_size = AES_IV_SIZE; + specs->block_size = AES_BLOCK_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_triple_des; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = DES3_KEY_SIZE; + specs->block_size = DES_BLOCK_SIZE; #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) - ssl->specs.iv_size = DES_BLOCK_SIZE; + specs->iv_size = DES_BLOCK_SIZE; #else - ssl->specs.iv_size = DES_IV_SIZE; + specs->iv_size = DES_IV_SIZE; #endif break; @@ -754,37 +841,37 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA case TLS_ECDH_RSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; + specs->bulk_cipher_algorithm = wolfssl_rc4; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = RC4_KEY_SIZE; + specs->iv_size = 0; + specs->block_size = 0; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_triple_des; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = DES3_KEY_SIZE; + specs->block_size = DES_BLOCK_SIZE; #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) - ssl->specs.iv_size = DES_BLOCK_SIZE; + specs->iv_size = DES_BLOCK_SIZE; #else - ssl->specs.iv_size = DES_IV_SIZE; + specs->iv_size = DES_IV_SIZE; #endif break; @@ -792,140 +879,140 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; + specs->bulk_cipher_algorithm = wolfssl_rc4; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = RC4_KEY_SIZE; + specs->iv_size = 0; + specs->block_size = 0; break; #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = ecc_diffie_hellman_kea; - ssl->specs.sig_algo = ecc_dsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 1; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = ecc_diffie_hellman_kea; + specs->sig_algo = ecc_dsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 1; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif @@ -934,187 +1021,193 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 case TLS_RSA_WITH_AES_128_CCM_8 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 case TLS_RSA_WITH_AES_256_CCM_8 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 case TLS_PSK_WITH_AES_128_CCM_8 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 case TLS_PSK_WITH_AES_256_CCM_8 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CCM case TLS_PSK_WITH_AES_128_CCM : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_16_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CCM case TLS_PSK_WITH_AES_256_CCM : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_16_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM case TLS_DHE_PSK_WITH_AES_128_CCM : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_16_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM case TLS_DHE_PSK_WITH_AES_256_CCM : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_CCM_16_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) #ifdef BUILD_TLS_SHA256_SHA256 case TLS_SHA256_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.block_size = 0; - ssl->specs.iv_size = HMAC_NONCE_SZ; - ssl->specs.aead_mac_size = WC_SHA256_DIGEST_SIZE; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = WC_SHA256_DIGEST_SIZE; + specs->block_size = 0; + specs->iv_size = HMAC_NONCE_SZ; + specs->aead_mac_size = WC_SHA256_DIGEST_SIZE; break; #endif #ifdef BUILD_TLS_SHA384_SHA384 case TLS_SHA384_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.block_size = 0; - ssl->specs.iv_size = HMAC_NONCE_SZ; - ssl->specs.aead_mac_size = WC_SHA384_DIGEST_SIZE; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = WC_SHA384_DIGEST_SIZE; + specs->block_size = 0; + specs->iv_size = HMAC_NONCE_SZ; + specs->aead_mac_size = WC_SHA384_DIGEST_SIZE; break; #endif @@ -1127,97 +1220,98 @@ int SetCipherSpecs(WOLFSSL* ssl) } /* if */ /* TLSi v1.3 cipher suites, 0x13 */ - if (ssl->options.cipherSuite0 == TLS13_BYTE) { - switch (ssl->options.cipherSuite) { + if (cipherSuite0 == TLS13_BYTE) { + switch (cipherSuite) { #ifdef WOLFSSL_TLS13 #ifdef BUILD_TLS_AES_128_GCM_SHA256 case TLS_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_NONCE_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_NONCE_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_AES_256_GCM_SHA384 case TLS_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_NONCE_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_NONCE_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 case TLS_CHACHA20_POLY1305_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CHACHA20_256_KEY_SIZE; - ssl->specs.block_size = CHACHA20_BLOCK_SIZE; - ssl->specs.iv_size = CHACHA20_IV_SIZE; - ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; - ssl->options.oldPoly = 0; /* use recent padding RFC */ + specs->bulk_cipher_algorithm = wolfssl_chacha; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CHACHA20_256_KEY_SIZE; + specs->block_size = CHACHA20_BLOCK_SIZE; + specs->iv_size = CHACHA20_IV_SIZE; + specs->aead_mac_size = POLY1305_AUTH_SZ; + if (opts != NULL) + opts->oldPoly = 0; /* use recent padding RFC */ break; #endif #ifdef BUILD_TLS_AES_128_CCM_SHA256 case TLS_AES_128_CCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_NONCE_SZ; - ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_NONCE_SZ; + specs->aead_mac_size = AES_CCM_16_AUTH_SZ; break; #endif #ifdef BUILD_TLS_AES_128_CCM_8_SHA256 case TLS_AES_128_CCM_8_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = 0; - ssl->specs.sig_algo = 0; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_NONCE_SZ; - ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_ccm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = 0; + specs->sig_algo = 0; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_NONCE_SZ; + specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; #endif @@ -1227,27 +1321,28 @@ int SetCipherSpecs(WOLFSSL* ssl) } } - if (ssl->options.cipherSuite0 == ECDHE_PSK_BYTE) { + if (cipherSuite0 == ECDHE_PSK_BYTE) { - switch (ssl->options.cipherSuite) { + switch (cipherSuite) { #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) #ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 case TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = ecdhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = ecdhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #endif @@ -1258,62 +1353,62 @@ int SetCipherSpecs(WOLFSSL* ssl) } - if (ssl->options.cipherSuite0 != ECC_BYTE && - ssl->options.cipherSuite0 != ECDHE_PSK_BYTE && - ssl->options.cipherSuite0 != CHACHA_BYTE && - ssl->options.cipherSuite0 != TLS13_BYTE) { /* normal suites */ - switch (ssl->options.cipherSuite) { + if (cipherSuite0 != ECC_BYTE && + cipherSuite0 != ECDHE_PSK_BYTE && + cipherSuite0 != CHACHA_BYTE && + cipherSuite0 != TLS13_BYTE) { /* normal suites */ + switch (cipherSuite) { #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA case SSL_RSA_WITH_RC4_128_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; + specs->bulk_cipher_algorithm = wolfssl_rc4; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = RC4_KEY_SIZE; + specs->iv_size = 0; + specs->block_size = 0; break; #endif #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 case SSL_RSA_WITH_RC4_128_MD5 : - ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = md5_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; - ssl->specs.pad_size = PAD_MD5; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = RC4_KEY_SIZE; - ssl->specs.iv_size = 0; - ssl->specs.block_size = 0; + specs->bulk_cipher_algorithm = wolfssl_rc4; + specs->cipher_type = stream; + specs->mac_algorithm = md5_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_MD5_DIGEST_SIZE; + specs->pad_size = PAD_MD5; + specs->static_ecdh = 0; + specs->key_size = RC4_KEY_SIZE; + specs->iv_size = 0; + specs->block_size = 0; break; #endif #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA case SSL_RSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; + specs->bulk_cipher_algorithm = wolfssl_triple_des; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = DES3_KEY_SIZE; + specs->block_size = DES_BLOCK_SIZE; #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) - ssl->specs.iv_size = DES_BLOCK_SIZE; + specs->iv_size = DES_BLOCK_SIZE; #else - ssl->specs.iv_size = DES_IV_SIZE; + specs->iv_size = DES_IV_SIZE; #endif break; @@ -1321,736 +1416,753 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA case TLS_RSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 case TLS_RSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_NULL_MD5 case TLS_RSA_WITH_NULL_MD5 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = md5_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; - ssl->specs.pad_size = PAD_MD5; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = md5_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_MD5_DIGEST_SIZE; + specs->pad_size = PAD_MD5; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; break; #endif #ifdef BUILD_TLS_RSA_WITH_NULL_SHA case TLS_RSA_WITH_NULL_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; break; #endif #ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 case TLS_RSA_WITH_NULL_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; break; #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA case TLS_RSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 case TLS_RSA_WITH_AES_256_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 case TLS_PSK_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 case TLS_PSK_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 case TLS_DH_anon_WITH_AES_256_GCM_SHA384: - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; - ssl->options.usingAnon_cipher = 1; + if (opts != NULL) + opts->usingAnon_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 case TLS_PSK_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 case TLS_PSK_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha384_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha384_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA case TLS_PSK_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA case TLS_PSK_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 case TLS_PSK_WITH_NULL_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha256_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 case TLS_PSK_WITH_NULL_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha384_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_PSK_WITH_NULL_SHA case TLS_PSK_WITH_NULL_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha_mac; + specs->kea = psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 case TLS_DHE_PSK_WITH_NULL_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha256_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 case TLS_DHE_PSK_WITH_NULL_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = dhe_psk_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = 0; - ssl->specs.block_size = 0; - ssl->specs.iv_size = 0; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha384_mac; + specs->kea = dhe_psk_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = 0; + specs->block_size = 0; + specs->iv_size = 0; - ssl->options.usingPSK_cipher = 1; + if (opts != NULL) + opts->usingPSK_cipher = 1; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = DES3_KEY_SIZE; - ssl->specs.block_size = DES_BLOCK_SIZE; - ssl->specs.iv_size = DES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_triple_des; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = DES3_KEY_SIZE; + specs->block_size = DES_BLOCK_SIZE; + specs->iv_size = DES_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA case TLS_DHE_RSA_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA case TLS_DHE_RSA_WITH_AES_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 case TLS_RSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 case TLS_RSA_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; - ssl->specs.cipher_type = aead; - ssl->specs.mac_algorithm = sha384_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_256_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AESGCM_IMP_IV_SZ; - ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + specs->bulk_cipher_algorithm = wolfssl_aes_gcm; + specs->cipher_type = aead; + specs->mac_algorithm = sha384_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA384_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_256_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AESGCM_IMP_IV_SZ; + specs->aead_mac_size = AES_GCM_AUTH_SZ; break; #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_128_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_256_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_128_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = rsa_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = rsa_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_256_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_128_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_256_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_128_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = rsa_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; - ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; - ssl->specs.iv_size = CAMELLIA_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_camellia; + specs->cipher_type = block; + specs->mac_algorithm = sha256_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = rsa_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = CAMELLIA_256_KEY_SIZE; + specs->block_size = CAMELLIA_BLOCK_SIZE; + specs->iv_size = CAMELLIA_IV_SIZE; break; #endif #ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA case TLS_DH_anon_WITH_AES_128_CBC_SHA : - ssl->specs.bulk_cipher_algorithm = wolfssl_aes; - ssl->specs.cipher_type = block; - ssl->specs.mac_algorithm = sha_mac; - ssl->specs.kea = diffie_hellman_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; - ssl->specs.static_ecdh = 0; - ssl->specs.key_size = AES_128_KEY_SIZE; - ssl->specs.block_size = AES_BLOCK_SIZE; - ssl->specs.iv_size = AES_IV_SIZE; + specs->bulk_cipher_algorithm = wolfssl_aes; + specs->cipher_type = block; + specs->mac_algorithm = sha_mac; + specs->kea = diffie_hellman_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA_DIGEST_SIZE; + specs->pad_size = PAD_SHA; + specs->static_ecdh = 0; + specs->key_size = AES_128_KEY_SIZE; + specs->block_size = AES_BLOCK_SIZE; + specs->iv_size = AES_IV_SIZE; - ssl->options.usingAnon_cipher = 1; + if (opts != NULL) + opts->usingAnon_cipher = 1; break; #endif #ifdef BUILD_WDM_WITH_NULL_SHA256 case WDM_WITH_NULL_SHA256 : - ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; - ssl->specs.cipher_type = stream; - ssl->specs.mac_algorithm = sha256_mac; - ssl->specs.kea = no_kea; - ssl->specs.sig_algo = anonymous_sa_algo; - ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; - ssl->specs.pad_size = PAD_SHA; + specs->bulk_cipher_algorithm = wolfssl_cipher_null; + specs->cipher_type = stream; + specs->mac_algorithm = sha256_mac; + specs->kea = no_kea; + specs->sig_algo = anonymous_sa_algo; + specs->hash_size = WC_SHA256_DIGEST_SIZE; + specs->pad_size = PAD_SHA; break; #endif @@ -2062,54 +2174,9 @@ int SetCipherSpecs(WOLFSSL* ssl) } /* switch */ } /* if ECC / Normal suites else */ - /* set TLS if it hasn't been turned off */ - if (ssl->version.major == SSLv3_MAJOR && - ssl->version.minor >= TLSv1_MINOR) { -#ifndef NO_TLS - ssl->options.tls = 1; - #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) - #if !defined(WOLFSSL_RENESAS_SCEPROTECT) && \ - !defined(WOLFSSL_RENESAS_TSIP_TLS) - ssl->hmac = TLS_hmac; - #else - ssl->hmac = Renesas_cmn_TLS_hmac; - #endif - #endif - if (ssl->version.minor >= TLSv1_1_MINOR) { - ssl->options.tls1_1 = 1; - if (ssl->version.minor >= TLSv1_3_MINOR) - ssl->options.tls1_3 = 1; - } -#endif - } - -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls && - ssl->version.major == DTLS_MAJOR && - ssl->version.minor <= DTLSv1_3_MINOR) { - ssl->options.tls = 1; - ssl->options.tls1_3 = 1; - } -#endif /* WOLFSSL_DTLS13 */ - -#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block) - ssl->options.encThenMac = 0; -#endif - -#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_AEAD_ONLY) - if (ssl->options.dtls) - #if !defined(WOLFSSL_RENESAS_SCEPROTECT) && \ - !defined(WOLFSSL_RENESAS_TSIP_TLS) - ssl->hmac = TLS_hmac; - #else - ssl->hmac = Renesas_cmn_TLS_hmac; - #endif -#endif - - if (ssl->specs.sig_algo == anonymous_sa_algo) { + if (specs->sig_algo == anonymous_sa_algo && opts != NULL) { /* CLIENT/SERVER: No peer authentication to be performed. */ - ssl->options.peerAuthGood = 1; + opts->peerAuthGood = 1; } return 0; diff --git a/src/ssl.c b/src/ssl.c index 9187f830b..adc3c1eb4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -13288,6 +13288,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.dtls = 1; ssl->options.tls = 1; ssl->options.tls1_1 = 1; + ssl->options.dtlsStateful = 1; } #endif @@ -13837,6 +13838,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.dtls = 1; ssl->options.tls = 1; ssl->options.tls1_1 = 1; + if (!IsDtlsNotSctpMode(ssl) || !IsDtlsNotSrtpMode(ssl) || + IsSCR(ssl)) + ssl->options.dtlsStateful = 1; } #endif @@ -35408,7 +35412,7 @@ void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char ** #endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ #ifdef OPENSSL_EXTRA -int wolfSSL_curve_is_disabled(WOLFSSL* ssl, word16 curve_id) +int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id) { return (curve_id <= WOLFSSL_ECC_MAX && ssl->disabledCurves && diff --git a/src/tls.c b/src/tls.c index 18371c471..815da07cf 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1310,6 +1310,38 @@ static TLSX* TLSX_New(TLSX_Type type, const void* data, void* heap) return extension; } +/** + * Creates a new extension and appends it to the provided list. + * Checks for duplicate extensions, keeps the newest. + */ +int TLSX_Append(TLSX** list, TLSX_Type type, const void* data, void* heap) +{ + TLSX* extension = TLSX_New(type, data, heap); + TLSX* cur; + TLSX** prevNext = list; + + if (extension == NULL) + return MEMORY_E; + + for (cur = *list; cur != NULL;) { + if (cur->type == type) { + *prevNext = cur->next; + cur->next = NULL; + TLSX_FreeAll(cur, heap); + cur = *prevNext; + } + else { + prevNext = &cur->next; + cur = cur->next; + } + } + + /* Append the extension to the list */ + *prevNext = extension; + + return 0; +} + /** * Creates a new extension and pushes it to the provided list. * Checks for duplicate extensions, keeps the newest. @@ -1345,43 +1377,6 @@ int TLSX_Push(TLSX** list, TLSX_Type type, const void* data, void* heap) return 0; } -#ifdef WOLFSSL_TLS13 - -/** - * Creates a new extension and prepend it to the provided list. - * Checks for duplicate extensions, keeps the newest. - */ -static int TLSX_Prepend(TLSX** list, TLSX_Type type, void* data, void* heap) -{ - TLSX* extension = TLSX_New(type, data, heap); - TLSX* curr = *list; - - if (extension == NULL) - return MEMORY_E; - - /* remove duplicate extensions, there should be only one of each type. */ - while (curr && curr->next) { - if (curr->next->type == type) { - TLSX *next = curr->next; - - curr->next = next->next; - next->next = NULL; - - TLSX_FreeAll(next, heap); - } - curr = curr->next; - } - - if (curr) - curr->next = extension; - else - *list = extension; - - return 0; -} - -#endif /* WOLFSSL_TLS13 */ - #ifndef NO_WOLFSSL_CLIENT int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type); @@ -4133,8 +4128,8 @@ static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output) #if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) -static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, const byte* input, - word16 length, byte isRequest) +int TLSX_SupportedCurve_Parse(const WOLFSSL* ssl, const byte* input, + word16 length, byte isRequest, TLSX** extensions) { word16 offset; word16 name; @@ -4166,7 +4161,7 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, const byte* input, TLSX* extension; SupportedCurve* curve; - extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); if (extension != NULL) { /* Replace client list with server list of supported groups. */ curve = (SupportedCurve*)extension->data; @@ -4187,7 +4182,7 @@ static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, const byte* input, for (; offset < length; offset += OPAQUE16_LEN) { ato16(input + offset, &name); - ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); + ret = TLSX_UseSupportedCurve(extensions, name, ssl->heap); /* If it is BAD_FUNC_ARG then it is a group we do not support, but * that is fine. */ if (ret != WOLFSSL_SUCCESS && ret != BAD_FUNC_ARG) { @@ -4546,7 +4541,8 @@ static int TLSX_PointFormat_Parse(WOLFSSL* ssl, const byte* input, } #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) -int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) { +int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, + CipherSuite* cs) { TLSX* extension = NULL; SupportedCurve* curve = NULL; word32 oid = 0; @@ -4866,21 +4862,21 @@ int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) { #endif { key = 1; - ssl->ecdhCurveOID = defOid; + cs->ecdhCurveOID = defOid; } /* Choose any curve at the required strength. */ if (ssl->ecdhCurveOID == 0) { key = 1; - ssl->ecdhCurveOID = currOid; + cs->ecdhCurveOID = currOid; } /* Choose the default if it is at the next highest strength. */ - if (ssl->ecdhCurveOID == 0 && defSz == nextSz) - ssl->ecdhCurveOID = defOid; + if (cs->ecdhCurveOID == 0 && defSz == nextSz) + cs->ecdhCurveOID = defOid; /* Choose any curve at the next highest strength. */ - if (ssl->ecdhCurveOID == 0) - ssl->ecdhCurveOID = nextOid; + if (cs->ecdhCurveOID == 0) + cs->ecdhCurveOID = nextOid; /* No curve and ephemeral ECC suite requires a matching curve. */ - if (ssl->ecdhCurveOID == 0 && ephmSuite) + if (cs->ecdhCurveOID == 0 && ephmSuite) key = 0; return key; @@ -4975,7 +4971,7 @@ int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap) !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) #define EC_PARSE TLSX_SupportedCurve_Parse #else -#define EC_PARSE(a, b, c, d) 0 +#define EC_PARSE(a, b, c, d, e) 0 #endif #define PF_FREE_ALL TLSX_PointFormat_FreeAll @@ -4996,7 +4992,7 @@ int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap) #define EC_FREE_ALL(list, heap) #define EC_GET_SIZE(list) 0 #define EC_WRITE(a, b) 0 -#define EC_PARSE(a, b, c, d) 0 +#define EC_PARSE(a, b, c, d, e) 0 #define EC_VALIDATE_REQUEST(a, b) #define PF_FREE_ALL(list, heap) @@ -6021,15 +6017,19 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, * input The buffer with the extension data. * length The length of the extension data. * msgType The type of the message this extension is being parsed from. + * pv The output ProtocolVersion for the negotiated version + * opts The output options structure. Can be NULL. + * exts The output extensions list. Can be NULL. * returns 0 on success, otherwise failure. */ -static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, - word16 length, byte msgType) +int TLSX_SupportedVersions_Parse(const WOLFSSL* ssl, const byte* input, + word16 length, byte msgType, ProtocolVersion* pv, Options* opts, + TLSX** exts) { - ProtocolVersion pv = ssl->ctx->method->version; int i; int len; - byte newMinor = 0; + /* The client's greatest minor version that we support */ + byte clientGreatestMinor = SSLv3_MINOR; int set = 0; int ret; byte major, minor; @@ -6044,6 +6044,7 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, if (ssl->options.dtls) { tls13minor = DTLSv1_3_MINOR; tls12minor = DTLSv1_2_MINOR; + clientGreatestMinor = DTLS_MINOR; } #endif /* WOLFSSL_DTLS13 */ @@ -6075,7 +6076,7 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, continue; #endif - if (major != pv.major) + if (major != ssl->ctx->method->version.major) continue; /* No upgrade allowed. */ @@ -6087,46 +6088,40 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, if (!ssl->options.downgrade) continue; - if (versionIsLesser( - isDtls, minor, ssl->options.minDowngrade)) + if (versionIsLesser(isDtls, minor, ssl->options.minDowngrade)) continue; - - if (newMinor == 0 && - versionIsGreater( - isDtls, minor, ssl->options.oldMinor)) { - /* Downgrade the version. */ - ssl->version.minor = minor; - } } - - if (versionIsAtLeast(isDtls, minor, tls13minor)) { - ssl->options.tls1_3 = 1; - - /* TLS v1.3 requires supported version extension */ - if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) { - ret = TLSX_Prepend(&ssl->extensions, - TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); - if (ret != 0) { - return ret; - } - TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); - } - if (versionIsGreater(isDtls, minor, newMinor)) { - ssl->version.minor = minor; - newMinor = minor; - } - } - else if (versionIsGreater( - isDtls, minor, ssl->options.oldMinor)) - ssl->options.oldMinor = minor; + if (versionIsGreater(isDtls, minor, clientGreatestMinor)) + clientGreatestMinor = minor; set = 1; } if (!set) { - SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version); + /* No common supported version was negotiated */ + SendAlert((WOLFSSL*)ssl, alert_fatal, + wolfssl_alert_protocol_version); WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); return VERSION_ERROR; } + pv->minor = clientGreatestMinor; + if (versionIsAtLeast(isDtls, clientGreatestMinor, tls13minor)) { + if (opts != NULL) + opts->tls1_3 = 1; + + /* TLS v1.3 requires supported version extension */ + if (exts != NULL && + TLSX_Find(*exts, TLSX_SUPPORTED_VERSIONS) == NULL) { + ret = TLSX_Push(exts, + TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); + if (ret != 0) { + return ret; + } + /* *exts should be pointing to the TLSX_SUPPORTED_VERSIONS + * ext in the list since it was pushed. */ + (*exts)->resp = 1; + } + } + } else if (msgType == server_hello || msgType == hello_retry_request) { /* Must contain one version. */ @@ -6136,7 +6131,7 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, major = input[0]; minor = input[OPAQUE8_LEN]; - if (major != pv.major) { + if (major != ssl->ctx->method->version.major) { WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); return VERSION_ERROR; } @@ -6150,7 +6145,7 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */ if (ssl->options.downgrade && ssl->version.minor == tls12minor) { /* Set minor version back to TLS v1.3+ */ - ssl->version.minor = ssl->ctx->method->version.minor; + pv->minor = ssl->ctx->method->version.minor; } /* No upgrade allowed. */ @@ -6173,7 +6168,7 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, const byte* input, } /* Downgrade the version. */ - ssl->version.minor = minor; + pv->minor = minor; } } else { @@ -6208,7 +6203,7 @@ static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, #define SV_GET_SIZE(a, b, c) 0 #define SV_WRITE(a, b, c, d) 0 -#define SV_PARSE(a, b, c, d) 0 +#define SV_PARSE(a, b, c, d, e, f, g) 0 #endif /* WOLFSSL_TLS13 */ @@ -6265,7 +6260,7 @@ static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType, if (msgType == client_hello || msgType == hello_retry_request) { c16toa(cookie->len, output); output += OPAQUE16_LEN; - XMEMCPY(output, &cookie->data, cookie->len); + XMEMCPY(output, cookie->data, cookie->len); *pSz += OPAQUE16_LEN + cookie->len; } else { @@ -6308,7 +6303,8 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_E; if (msgType == hello_retry_request) - return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0); + return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0, + &ssl->extensions); /* client_hello */ extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); @@ -6318,7 +6314,8 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* Allow a cookie extension with DTLS 1.3 because it is possible * that a different SSL instance sent the cookie but we are now * receiving it. */ - return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0); + return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0, + &ssl->extensions); else #endif { @@ -6328,7 +6325,7 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length, } cookie = (Cookie*)extension->data; - if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0) { + if (cookie->len != len || XMEMCMP(cookie->data, input + idx, len) != 0) { WOLFSSL_ERROR_VERBOSE(HRR_COOKIE_ERROR); return HRR_COOKIE_ERROR; } @@ -6349,36 +6346,35 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length, * resp Indicates the extension will go into a response (HelloRetryRequest). * returns 0 on success and other values indicate failure. */ -int TLSX_Cookie_Use(WOLFSSL* ssl, const byte* data, word16 len, byte* mac, - byte macSz, int resp) +int TLSX_Cookie_Use(const WOLFSSL* ssl, const byte* data, word16 len, byte* mac, + byte macSz, int resp, TLSX** exts) { int ret = 0; TLSX* extension; Cookie* cookie; /* Find the cookie extension if it exists. */ - extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + extension = TLSX_Find(*exts, TLSX_COOKIE); if (extension == NULL) { /* Push new cookie extension. */ - ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap); + ret = TLSX_Push(exts, TLSX_COOKIE, NULL, ssl->heap); if (ret != 0) return ret; - extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + extension = TLSX_Find(*exts, TLSX_COOKIE); if (extension == NULL) return MEMORY_E; } - /* The Cookie structure has one byte for cookie data already. */ - cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap, + cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz, ssl->heap, DYNAMIC_TYPE_TLSX); if (cookie == NULL) return MEMORY_E; cookie->len = len + macSz; - XMEMCPY(&cookie->data, data, len); + XMEMCPY(cookie->data, data, len); if (mac != NULL) - XMEMCPY(&cookie->data + len, mac, macSz); + XMEMCPY(cookie->data + len, mac, macSz); if (extension->data != NULL) XFREE(extension->data, ssl->heap, DYNAMIC_TYPE_TLSX); @@ -8205,8 +8201,8 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) * returns a positive number to indicate amount of data parsed and a negative * number on error. */ -static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, const byte* input, - word16 length, KeyShareEntry **kse) +static int TLSX_KeyShareEntry_Parse(const WOLFSSL* ssl, const byte* input, + word16 length, KeyShareEntry **kse, TLSX** extensions) { int ret; word16 group; @@ -8244,7 +8240,7 @@ static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, const byte* input, } /* Populate a key share object in the extension. */ - ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse); + ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse, extensions); if (ret != 0) { if (ke != &input[offset]) { XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); @@ -8291,13 +8287,14 @@ static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group) * name The group name to match. * returns 1 when the extension has the group name and 0 otherwise. */ -static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) +static int TLSX_SupportedGroups_Find(const WOLFSSL* ssl, word16 name, + TLSX* extensions) { #ifdef HAVE_SUPPORTED_CURVES TLSX* extension; SupportedCurve* curve = NULL; - if ((extension = TLSX_Find(ssl->extensions, + if ((extension = TLSX_Find(extensions, TLSX_SUPPORTED_GROUPS)) == NULL) { if ((extension = TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS)) == NULL) { @@ -8317,6 +8314,45 @@ static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) return 0; } +int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl, + const byte* input, word16 length, TLSX** extensions) +{ + int ret; + int offset = 0; + word16 len; + TLSX* extension; + + /* Add a KeyShare extension if it doesn't exist even if peer sent no + * entries. The presence of this extension signals that the peer can be + * negotiated with. */ + extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + } + + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* ClientHello contains zero or more key share entries. */ + ato16(input, &len); + if (len != length - OPAQUE16_LEN) + return BUFFER_ERROR; + offset += OPAQUE16_LEN; + + while (offset < (int)length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], + length - (word16)offset, NULL, extensions); + if (ret < 0) + return ret; + + offset += ret; + } + + return 0; +} /* Parse the KeyShare extension. * Different formats in different messages. @@ -8327,7 +8363,7 @@ static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) * msgType The type of the message this extension is being parsed from. * returns 0 on success and other values indicate failure. */ -static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, +int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType) { int ret; @@ -8335,39 +8371,8 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, word16 group; if (msgType == client_hello) { - int offset = 0; - word16 len; - TLSX* extension; - - /* Add a KeyShare extension if it doesn't exist. */ - extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); - if (extension == NULL) { - /* Push new KeyShare extension. */ - ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); - if (ret != 0) - return ret; - } - - if (length < OPAQUE16_LEN) - return BUFFER_ERROR; - - /* ClientHello contains zero or more key share entries. */ - ato16(input, &len); - if (len != length - OPAQUE16_LEN) - return BUFFER_ERROR; - offset += OPAQUE16_LEN; - - while (offset < (int)length) { - ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], - length - (word16)offset, - &keyShareEntry); - if (ret < 0) - return ret; - - offset += ret; - } - - ret = 0; + ret = TLSX_KeyShare_Parse_ClientHello(ssl, input, length, + &ssl->extensions); } else if (msgType == server_hello) { int len; @@ -8379,7 +8384,7 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, ato16(input, &group); /* Check the selected group was supported by ClientHello extensions. */ - if (!TLSX_SupportedGroups_Find(ssl, group)) { + if (!TLSX_SupportedGroups_Find(ssl, group, ssl->extensions)) { WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA); return BAD_KEY_SHARE_DATA; } @@ -8391,7 +8396,8 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, } /* ServerHello contains one key share entry. */ - len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); + len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry, + &ssl->extensions); if (len != (int)length) return BUFFER_ERROR; @@ -8423,7 +8429,7 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, #endif { /* Check the selected group was supported by ClientHello extensions. */ - if (!TLSX_SupportedGroups_Find(ssl, group)) { + if (!TLSX_SupportedGroups_Find(ssl, group, ssl->extensions)) { WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA); return BAD_KEY_SHARE_DATA; } @@ -8444,7 +8450,7 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* For post-quantum groups, do this in TLSX_PopulateExtensions(). */ if (!WOLFSSL_NAMED_GROUP_IS_PQC(group)) #endif - ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL, &ssl->extensions); } else { /* Not a message type that is allowed to have this extension. */ @@ -8662,22 +8668,22 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, * kse The new key share entry object. * returns 0 on success and other values indicate failure. */ -int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, - KeyShareEntry **kse) +int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, + KeyShareEntry **kse, TLSX** extensions) { int ret = 0; TLSX* extension; KeyShareEntry* keyShareEntry = NULL; /* Find the KeyShare extension if it exists. */ - extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); if (extension == NULL) { /* Push new KeyShare extension. */ - ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap); if (ret != 0) return ret; - extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); if (extension == NULL) return MEMORY_E; } @@ -8703,7 +8709,7 @@ int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, #ifdef HAVE_PQC if (WOLFSSL_NAMED_GROUP_IS_PQC(group) && ssl->options.side == WOLFSSL_SERVER_END) { - ret = server_generate_pqc_ciphertext(ssl, keyShareEntry, data, + ret = server_generate_pqc_ciphertext((WOLFSSL*)ssl, keyShareEntry, data, len); if (ret != 0) return ret; @@ -8718,8 +8724,11 @@ int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, keyShareEntry->keLen = len; } else { - /* Generate a key pair. */ - ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry); + /* Generate a key pair. Casting to non-const since changes inside are + * minimal but would require an extensive redesign to refactor. Also + * this path shouldn't be taken when parsing a ClientHello in stateless + * mode. */ + ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, keyShareEntry); if (ret != 0) return ret; } @@ -8905,6 +8914,69 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) return 1; } + +static const word16 preferredGroup[] = { +#if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_ECC_SECP256R1, +#endif +#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_ECC_X25519, +#endif +#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + WOLFSSL_ECC_X448, +#endif +#if defined(HAVE_ECC) && (!defined(NO_ECC384) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 384 + WOLFSSL_ECC_SECP384R1, +#endif +#if defined(HAVE_ECC) && (!defined(NO_ECC521) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 521 + WOLFSSL_ECC_SECP521R1, +#endif +#if defined(HAVE_FFDHE_2048) + WOLFSSL_FFDHE_2048, +#endif +#if defined(HAVE_FFDHE_3072) + WOLFSSL_FFDHE_3072, +#endif +#if defined(HAVE_FFDHE_4096) + WOLFSSL_FFDHE_4096, +#endif +#if defined(HAVE_FFDHE_6144) + WOLFSSL_FFDHE_6144, +#endif +#if defined(HAVE_FFDHE_8192) + WOLFSSL_FFDHE_8192, +#endif +#ifdef WOLFSSL_WC_KYBER + #ifdef WOLFSSL_KYBER512 + WOLFSSL_KYBER_LEVEL1, + #endif + #ifdef WOLFSSL_KYBER768 + WOLFSSL_KYBER_LEVEL3, + #endif + #ifdef WOLFSSL_KYBER1024 + WOLFSSL_KYBER_LEVEL5, + #endif +#elif defined(HAVE_LIBOQS) + /* These require a runtime call to TLSX_KeyShare_IsSupported to use */ + WOLFSSL_KYBER_LEVEL1, + WOLFSSL_KYBER_LEVEL3, + WOLFSSL_KYBER_LEVEL5, + WOLFSSL_P256_KYBER_LEVEL1, + WOLFSSL_P384_KYBER_LEVEL3, + WOLFSSL_P521_KYBER_LEVEL5, +#elif defined(HAVE_PQM4) + WOLFSSL_KYBER_LEVEL1, +#endif + WOLFSSL_NAMED_GROUP_INVALID +}; + +#define PREFERRED_GROUP_SZ \ + ((sizeof(preferredGroup)/sizeof(*preferredGroup)) - 1) + /* -1 for the invalid group */ + /* Examines the application specified group ranking and returns the rank of the * group. * If no group ranking set then all groups are rank 0 (highest). @@ -8913,95 +8985,28 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) * group The group to check ranking for. * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list. */ -static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group) +static int TLSX_KeyShare_GroupRank(const WOLFSSL* ssl, int group) { byte i; + const word16* groups; + byte numGroups; if (ssl->numGroups == 0) { -#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 - #ifndef NO_ECC_SECP - ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1; - #endif - #endif -#endif - #ifndef HAVE_FIPS - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519; - #endif - #endif - #ifndef HAVE_FIPS - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X448; - #endif - #endif -#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384 - #ifndef NO_ECC_SECP - ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1; - #endif - #endif - #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521 - #ifndef NO_ECC_SECP - ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1; - #endif - #endif -#endif - /* Add FFDHE supported groups. */ - #ifdef HAVE_FFDHE_2048 - ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048; - #endif - #ifdef HAVE_FFDHE_3072 - ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072; - #endif - #ifdef HAVE_FFDHE_4096 - ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096; - #endif - #ifdef HAVE_FFDHE_6144 - ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144; - #endif - #ifdef HAVE_FFDHE_8192 - ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192; - #endif -#ifdef HAVE_PQC - /* For the liboqs groups we need to do a runtime check because - * liboqs could be compiled to make an algorithm unavailable. - */ - #ifdef WOLFSSL_WC_KYBER - #ifdef WOLFSSL_KYBER512 - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL1)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL1; - #endif - #ifdef WOLFSSL_KYBER768 - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL3)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL3; - #endif - #ifdef WOLFSSL_KYBER1024 - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL5)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL5; - #endif - #elif defined(HAVE_LIBOQS) - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL1)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL1; - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL3)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL3; - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL5)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL5; - if (TLSX_KeyShare_IsSupported(WOLFSSL_P256_KYBER_LEVEL1)) - ssl->group[ssl->numGroups++] = WOLFSSL_P256_KYBER_LEVEL1; - if (TLSX_KeyShare_IsSupported(WOLFSSL_P384_KYBER_LEVEL3)) - ssl->group[ssl->numGroups++] = WOLFSSL_P384_KYBER_LEVEL3; - if (TLSX_KeyShare_IsSupported(WOLFSSL_P521_KYBER_LEVEL5)) - ssl->group[ssl->numGroups++] = WOLFSSL_P521_KYBER_LEVEL5; - #elif defined(HAVE_PQM4) - if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER_LEVEL1)) - ssl->group[ssl->numGroups++] = WOLFSSL_KYBER_LEVEL1; - #endif /* HAVE_LIBOQS */ -#endif /* HAVE_PQC */ + groups = preferredGroup; + numGroups = PREFERRED_GROUP_SZ; + } + else { + groups = ssl->group; + numGroups = ssl->numGroups; } - for (i = 0; i < ssl->numGroups; i++) - if (ssl->group[i] == (word16)group) +#ifdef HAVE_LIBOQS + if (!TLSX_KeyShare_IsSupported(group)) + return -1; +#endif + + for (i = 0; i < numGroups; i++) + if (groups[i] == (word16)group) return i; return -1; @@ -9013,7 +9018,7 @@ static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group) * returns BAD_KEY_SHARE_DATA if no supported group has a key share, * 0 if a supported group has a key share and other values indicate an error. */ -static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) +int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions) { int ret; #ifdef HAVE_SUPPORTED_CURVES @@ -9023,7 +9028,7 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) int preferredRank = WOLFSSL_MAX_GROUP_COUNT; int rank; - extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); if (extension != NULL) curve = (SupportedCurve*)extension->data; /* Use server's preference order. */ @@ -9049,7 +9054,7 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) } /* Delete the old key share data list. */ - extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); if (extension != NULL) { KeyShareEntry* kse = (KeyShareEntry*)extension->data; #ifdef WOLFSSL_ASYNC_CRYPT @@ -9063,12 +9068,12 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) } /* Add in the chosen group. */ - ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); + ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL, extensions); if (ret != 0 && ret != WC_PENDING_E) return ret; /* Set extension to be in response. */ - extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); extension->resp = 1; #else @@ -9081,37 +9086,36 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) return ret; } -/* Ensure there is a key pair that can be used for key exchange. - * - * ssl The SSL/TLS object. - * doHelloRetry If set to non-zero will do hello_retry - * returns 0 on success and other values indicate failure. - */ -int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) +/* Server side KSE processing */ +int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, + KeyShareEntry** kse, byte* searched) { - int ret; TLSX* extension; KeyShareEntry* clientKSE = NULL; - KeyShareEntry* serverKSE; KeyShareEntry* list = NULL; KeyShareEntry* preferredKSE = NULL; int preferredRank = WOLFSSL_MAX_GROUP_COUNT; int rank; + if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END) + return BAD_FUNC_ARG; + + *searched = 0; + /* Find the KeyShare extension if it exists. */ - extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension = TLSX_Find(extensions, TLSX_KEY_SHARE); if (extension != NULL) list = (KeyShareEntry*)extension->data; if (extension && extension->resp == 1) { - ret = 0; + int ret = 0; #ifdef WOLFSSL_ASYNC_CRYPT /* in async case make sure key generation is finalized */ serverKSE = (KeyShareEntry*)extension->data; if (serverKSE->lastRet == WC_PENDING_E) { if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) *doHelloRetry = 1; - ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE); } #endif return ret; @@ -9123,7 +9127,7 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) continue; /* Check consistency now - extensions in any order. */ - if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group)) + if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group, extensions)) continue; if (!WOLFSSL_NAMED_GROUP_IS_FFHDE(clientKSE->group)) { @@ -9148,16 +9152,27 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) preferredRank = rank; } } - clientKSE = preferredKSE; + *kse = preferredKSE; + *searched = 1; + return 0; +} - /* No supported group found - send HelloRetryRequest. */ - if (clientKSE == NULL) { - /* Set KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ - *doHelloRetry = 1; - return TLSX_KeyShare_SetSupported(ssl); - } +/* Server side KSE processing */ +int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) +{ + int ret; + TLSX* extension; + KeyShareEntry* serverKSE; + KeyShareEntry* list = NULL; + + if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END || + clientKSE == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return BAD_STATE_E; - list = NULL; /* Generate a new key pair except in the case of OQS KEM because we * are going to encapsulate and that does not require us to generate a * key pair. @@ -9212,8 +9227,35 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) extension->data = (void *)serverKSE; extension->resp = 1; + return 0; +} - return ret; +/* Ensure there is a key pair that can be used for key exchange. + * + * ssl The SSL/TLS object. + * doHelloRetry If set to non-zero will do hello_retry + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) +{ + int ret; + KeyShareEntry* clientKSE = NULL; + byte searched = 0; + + *doHelloRetry = 0; + + ret = TLSX_KeyShare_Choose(ssl, ssl->extensions, &clientKSE, &searched); + if (ret != 0 || !searched) + return ret; + + /* No supported group found - send HelloRetryRequest. */ + if (clientKSE == NULL) { + /* Set KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + *doHelloRetry = 1; + return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions); + } + + return TLSX_KeyShare_Setup(ssl, clientKSE); } /* Derive the shared secret of the key exchange. @@ -9817,25 +9859,14 @@ static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, return SANITY_MSG_E; } -/* Parse the PSK KE modes 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_PskKeModes_Parse(WOLFSSL* ssl, const byte* input, word16 length, - byte msgType) +int TLSX_PskKeyModes_Parse_Modes(const byte* input, word16 length, byte msgType, + byte* modes) { - int ret; - if (msgType == client_hello) { /* Format: Len | Modes* */ int idx = 0; word16 len; - byte modes = 0; + *modes = 0; /* Ensure length byte exists. */ if (length < OPAQUE8_LEN) @@ -9851,15 +9882,10 @@ static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, const byte* input, word16 length, while (len > 0) { /* Ignore unrecognized modes. */ if (input[idx] <= PSK_DHE_KE) - modes |= 1 << input[idx]; + *modes |= 1 << input[idx]; idx++; len--; } - - ret = TLSX_PskKeModes_Use(ssl, modes); - if (ret != 0) - return ret; - return 0; } @@ -9867,13 +9893,36 @@ static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, const byte* input, word16 length, return SANITY_MSG_E; } +/* Parse the PSK KE modes 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_PskKeModes_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte msgType) +{ + int ret; + byte modes; + + ret = TLSX_PskKeyModes_Parse_Modes(input, length, msgType, &modes); + if (ret == 0) + ret = TLSX_PskKeyModes_Use(ssl, modes); + + WOLFSSL_ERROR_VERBOSE(ret); + return ret; +} + /* Use the data to create a new PSK Key Exchange Modes object in the extensions. * * ssl The SSL/TLS object. * modes The PSK key exchange modes. * returns 0 on success and other values indicate failure. */ -int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes) +int TLSX_PskKeyModes_Use(WOLFSSL* ssl, byte modes) { int ret = 0; TLSX* extension; @@ -11775,47 +11824,6 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) #endif /* HAVE_SUPPORTED_CURVES */ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) - -static const word16 preferredGroup[] = { -#if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ - defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_ECC_SECP256R1, -#endif -#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_ECC_X25519, -#endif -#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - WOLFSSL_ECC_X448, -#endif -#if defined(HAVE_ECC) && (!defined(NO_ECC384) || \ - defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 384 - WOLFSSL_ECC_SECP384R1, -#endif -#if defined(HAVE_ECC) && (!defined(NO_ECC521) || \ - defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 521 - WOLFSSL_ECC_SECP521R1, -#endif -#if defined(HAVE_FFDHE_2048) - WOLFSSL_FFDHE_2048, -#endif -#if defined(HAVE_FFDHE_3072) - WOLFSSL_FFDHE_3072, -#endif -#if defined(HAVE_FFDHE_4096) - WOLFSSL_FFDHE_4096, -#endif -#if defined(HAVE_FFDHE_6144) - WOLFSSL_FFDHE_6144, -#endif -#if defined(HAVE_FFDHE_8192) - WOLFSSL_FFDHE_8192, -#endif - WOLFSSL_NAMED_GROUP_INVALID -}; - -#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */ - int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) { int ret = 0; @@ -11930,17 +11938,34 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) namedGroup = preferredGroup[0]; for (i = 0; i < ssl->numGroups && !set; i++) { for (j = 0; preferredGroup[j] != WOLFSSL_NAMED_GROUP_INVALID; j++) { - if (preferredGroup[j] == ssl->group[i]) { + if (preferredGroup[j] == ssl->group[i] +#ifdef HAVE_LIBOQS + && TLSX_KeyShare_IsSupported(preferredGroup[j]) +#endif + ) { namedGroup = ssl->group[i]; set = 1; break; } } } + if (!set) + namedGroup = WOLFSSL_NAMED_GROUP_INVALID; } else { /* Choose the most preferred group. */ namedGroup = preferredGroup[0]; +#ifdef HAVE_LIBOQS + if (!TLSX_KeyShare_IsSupported(namedGroup)) { + int i = 1; + for (;preferredGroup[i] != WOLFSSL_NAMED_GROUP_INVALID; + i++) { + if (TLSX_KeyShare_IsSupported(preferredGroup[i])) + break; + } + namedGroup = preferredGroup[i]; + } +#endif } } else { @@ -11948,7 +11973,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (kse) namedGroup = kse->group; } - if (namedGroup > 0) { + if (namedGroup != WOLFSSL_NAMED_GROUP_INVALID) { #ifdef HAVE_PQC /* For KEMs, the key share has already been generated, but not * if we are resuming. */ @@ -11958,7 +11983,10 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif /* HAVE_SESSION_TICKET */ ) #endif /* HAVE_PQC */ - ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); + { + ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL, + &ssl->extensions); + } if (ret != 0) return ret; } @@ -12164,7 +12192,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) modes |= 1 << PSK_DHE_KE; } #endif - ret = TLSX_PskKeModes_Use(ssl, modes); + ret = TLSX_PskKeyModes_Use(ssl, modes); if (ret != 0) return ret; } @@ -12710,7 +12738,7 @@ int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) #ifdef WOLFSSL_TLS13 case hello_retry_request: XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); - TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); #ifdef HAVE_SUPPORTED_CURVES #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (!ssl->options.noPskDheKe) @@ -13001,7 +13029,8 @@ int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input, word16 length, WOLFSSL_MSG("Supported Versions extension received"); - ret = SV_PARSE(ssl, input + offset, size, msgType); + ret = SV_PARSE(ssl, input + offset, size, msgType, &ssl->version, + &ssl->options, &ssl->extensions); break; } @@ -13183,7 +13212,8 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, return EXT_NOT_ALLOWED; } } - ret = EC_PARSE(ssl, input + offset, size, isRequest); + ret = EC_PARSE(ssl, input + offset, size, isRequest, + &ssl->extensions); break; case TLSX_EC_POINT_FORMATS: diff --git a/src/tls13.c b/src/tls13.c index d6c9fe4b8..fd418f7d1 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3337,7 +3337,8 @@ byte SuiteMac(const byte* suite) * hashSz The size of the hash data in bytes. * returns 0 on success, otherwise failure. */ -static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz) +static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, byte hashSz, + TLSX** exts) { int ret; byte mac[WC_MAX_DIGEST_SIZE] = {0}; @@ -3380,7 +3381,7 @@ static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz) return ret; /* The cookie data is the hash and the integrity check. */ - return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1); + return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1, exts); } #endif @@ -3390,52 +3391,40 @@ static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz) #define HRR_MAX_HS_HEADER_SZ HANDSHAKE_HEADER_SZ #endif /* WOLFSSL_DTLS13 */ -/* Restart the handshake hash with a hash of the previous messages. - * - * ssl The SSL/TLS object. - * returns 0 on success, otherwise failure. - */ -int RestartHandshakeHash(WOLFSSL* ssl) +static int CreateCookieHash(const WOLFSSL* ssl, byte** hash, byte* hashSz, + Hashes* hashes, TLSX** exts) { int ret; - Hashes hashes; - byte header[HANDSHAKE_HEADER_SZ] = {0}; - byte* hash = NULL; - byte hashSz = 0; - ret = BuildCertHashes(ssl, &hashes); + (void)exts; + + ret = BuildCertHashes(ssl, hashes); if (ret != 0) return ret; + *hash = NULL; switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 case sha256_mac: - hash = hashes.sha256; + *hash = hashes->sha256; break; #endif #ifdef WOLFSSL_SHA384 case sha384_mac: - hash = hashes.sha384; + *hash = hashes->sha384; break; #endif #ifdef WOLFSSL_TLS13_SHA512 case sha512_mac: - hash = hashes.sha512; + *hash = hashes->sha512; break; #endif } - hashSz = ssl->specs.hash_size; + *hashSz = ssl->specs.hash_size; /* check hash */ - if (hash == NULL && hashSz > 0) + if (*hash == NULL && *hashSz > 0) return BAD_FUNC_ARG; - AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); - -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Restart Hash"); - WOLFSSL_BUFFER(hash, hashSz); -#endif - #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) { byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; @@ -3443,20 +3432,55 @@ int RestartHandshakeHash(WOLFSSL* ssl) word32 idx = 0; /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ - cookie[idx++] = hashSz; - if (hash) - XMEMCPY(cookie + idx, hash, hashSz); - idx += hashSz; + cookie[idx++] = *hashSz; + if (*hash) + XMEMCPY(cookie + idx, *hash, *hashSz); + idx += *hashSz; cookie[idx++] = ssl->options.cipherSuite0; cookie[idx++] = ssl->options.cipherSuite; if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) { KeyShareEntry* kse = (KeyShareEntry*)ext->data; + if (kse == NULL) { + WOLFSSL_MSG("KeyShareEntry can't be empty when negotiating " + "parameters"); + return BAD_STATE_E; + } c16toa(kse->group, cookie + idx); idx += OPAQUE16_LEN; } - return CreateCookie(ssl, cookie, idx); + ret = CreateCookieExt(ssl, cookie, idx, exts); } #endif + return ret; +} + +/* Restart the handshake hash with a hash of the previous messages. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int RestartHandshakeHash(WOLFSSL* ssl) +{ + int ret; + byte header[HANDSHAKE_HEADER_SZ] = {0}; + Hashes hashes; + byte* hash = NULL; + byte hashSz = 0; + + ret = CreateCookieHash(ssl, &hash, &hashSz, &hashes, &ssl->extensions); + if (ret != 0) + return ret; +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) + return 0; +#endif + + AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Restart Hash"); + WOLFSSL_BUFFER(hash, hashSz); +#endif ret = InitHandshakeHashes(ssl); if (ret != 0) @@ -5975,7 +5999,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, * cookieSz The length of the cookie data in bytes. * returns Length of the hash on success, otherwise failure. */ -static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz) +int TlsCheckCookie(const WOLFSSL* ssl, const byte* cookie, byte cookieSz) { int ret; byte mac[WC_MAX_DIGEST_SIZE] = {0}; @@ -6064,11 +6088,11 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) int keyShareExt = 0; int ret; - cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len); + cookieDataSz = ret = TlsCheckCookie(ssl, cookie->data, cookie->len); if (ret < 0) return ret; - hashSz = cookie->data; - cookieData = &cookie->data; + hashSz = cookie->data[0]; + cookieData = cookie->data; idx = OPAQUE8_LEN; /* Restart handshake hash with synthetic message hash. */ @@ -6346,6 +6370,22 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); #endif + /* do not change state in the SSL object before the next region of code + * to be able to statelessly compute a DTLS cookie */ +#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) + /* Update the ssl->options.dtlsStateful setting `if` statement in + * wolfSSL_accept_TLSv13 when changing this one. */ + if (IsDtlsNotSctpMode(ssl) && ssl->options.sendCookie) { + ret = DoClientHelloStateless(ssl, input, inOutIdx, helloSz); + if (ret != 0 || !ssl->options.dtlsStateful) { + *inOutIdx += helloSz; + DtlsResetState(ssl); + goto exit_dch; + } + } + ssl->options.dtlsStateful = 1; +#endif /* WOLFSSL_DTLS */ + args->idx = *inOutIdx; args->begin = args->idx; @@ -6761,8 +6801,21 @@ exit_dch: } #endif - if (ret == VERSION_ERROR) + if (ret == VERSION_ERROR) { +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if (((ssl->keys.dtls_sequence_number_hi == ssl->keys.curSeq_hi && + ssl->keys.dtls_sequence_number_lo < ssl->keys.curSeq_lo) || + (ssl->keys.dtls_sequence_number_hi < ssl->keys.curSeq_hi))) { + /* We should continue with the same sequence number as the + * Client Hello if available. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + } + } +#endif SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version); + } FreeDch13Args(ssl, args); #ifdef WOLFSSL_ASYNC_CRYPT @@ -11335,6 +11388,13 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) return ret; } +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.dtlsStateful = 1; + } +#endif + #ifdef WOLFSSL_WOLFSENTRY_HOOKS if ((ssl->ConnectFilter != NULL) && (ssl->options.connectState == CONNECT_BEGIN)) @@ -11843,7 +11903,7 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) (void)ret; (void)group; #else - ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL, &ssl->extensions); if (ret != 0) return ret; #endif /* NO_TLS */ @@ -12520,6 +12580,14 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) return ret; } +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + if (!IsDtlsNotSctpMode(ssl) || !ssl->options.sendCookie) + ssl->options.dtlsStateful = 1; + } +#endif + #ifdef WOLFSSL_WOLFSENTRY_HOOKS if ((ssl->AcceptFilter != NULL) && ((ssl->options.acceptState == TLS13_ACCEPT_BEGIN) diff --git a/tests/api.c b/tests/api.c index 2349b2b58..373beea55 100644 --- a/tests/api.c +++ b/tests/api.c @@ -37545,7 +37545,6 @@ static int test_wolfSSL_DTLS_either_side(void) callback_functions client_cb; callback_functions server_cb; -/* create a failed connection and inspect the error */ #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif @@ -59249,12 +59248,174 @@ static void test_wolfSSL_dtls_send_ch(WOLFSSL* ssl) AssertIntGT(ret, 0); } +#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) +static void test_wolfSSL_dtls_send_ch_with_invalid_cookie(WOLFSSL* ssl) +{ + int fd, ret; + byte ch_msh_invalid_cookie[] = { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x4e, 0x01, 0x00, 0x02, 0x42, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x42, 0xfe, 0xfd, 0x69, 0xca, 0x77, 0x60, 0x6f, 0xfc, 0xd1, 0x5b, 0x60, + 0x5d, 0xf1, 0xa6, 0x5c, 0x44, 0x71, 0xae, 0xca, 0x62, 0x19, 0x0c, 0xb6, + 0xf7, 0x2c, 0xa6, 0xd5, 0xd2, 0x99, 0x9d, 0x18, 0xae, 0xac, 0x11, 0x00, + 0x00, 0x00, 0x36, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x2c, 0xc0, + 0x2b, 0xc0, 0x30, 0xc0, 0x2f, 0x00, 0x9f, 0x00, 0x9e, 0xcc, 0xa9, 0xcc, + 0xa8, 0xcc, 0xaa, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x28, 0xc0, 0x24, 0xc0, + 0x0a, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x13, 0x00, 0x6b, 0x00, 0x67, 0x00, + 0x39, 0x00, 0x33, 0xcc, 0x14, 0xcc, 0x13, 0xcc, 0x15, 0x01, 0x00, 0x01, + 0xe2, 0x00, 0x2b, 0x00, 0x03, 0x02, 0xfe, 0xfc, 0x00, 0x0d, 0x00, 0x20, + 0x00, 0x1e, 0x06, 0x03, 0x05, 0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, + 0x08, 0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08, 0x09, 0x06, 0x01, + 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x2c, 0x00, 0x45, + 0x00, 0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x2d, 0x00, + 0x03, 0x02, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x19, + 0x00, 0x18, 0x00, 0x17, 0x00, 0x15, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x33, 0x01, 0x4b, 0x01, 0x49, 0x00, 0x17, 0x00, 0x41, 0x04, 0x7c, + 0x5a, 0xc2, 0x5a, 0xfd, 0xcd, 0x2b, 0x08, 0xb2, 0xeb, 0x8e, 0xc0, 0x02, + 0x03, 0x9d, 0xb1, 0xc1, 0x0d, 0x7b, 0x7f, 0x46, 0x43, 0xdf, 0xf3, 0xee, + 0x2b, 0x78, 0x0e, 0x29, 0x8c, 0x42, 0x11, 0x2c, 0xde, 0xd7, 0x41, 0x0f, + 0x28, 0x94, 0x80, 0x41, 0x70, 0xc4, 0x17, 0xfd, 0x6d, 0xfa, 0xee, 0x9a, + 0xf2, 0xc4, 0x15, 0x4c, 0x5f, 0x54, 0xb6, 0x78, 0x6e, 0xf9, 0x63, 0x27, + 0x33, 0xb8, 0x7b, 0x01, 0x00, 0x01, 0x00, 0xd4, 0x46, 0x62, 0x9c, 0xbf, + 0x8f, 0x1b, 0x65, 0x9b, 0xf0, 0x29, 0x64, 0xd8, 0x50, 0x0e, 0x74, 0xf1, + 0x58, 0x10, 0xc9, 0xd9, 0x82, 0x5b, 0xd9, 0xbe, 0x14, 0xdf, 0xde, 0x86, + 0xb4, 0x2e, 0x15, 0xee, 0x4f, 0xf6, 0x74, 0x9e, 0x59, 0x11, 0x36, 0x2d, + 0xb9, 0x67, 0xaa, 0x5a, 0x09, 0x9b, 0x45, 0xf1, 0x01, 0x4c, 0x4e, 0xf6, + 0xda, 0x6a, 0xae, 0xa7, 0x73, 0x7b, 0x2e, 0xb6, 0x24, 0x89, 0x99, 0xb7, + 0x52, 0x16, 0x62, 0x0a, 0xab, 0x58, 0xf8, 0x3f, 0x10, 0x5b, 0x83, 0xfd, + 0x7b, 0x81, 0x77, 0x81, 0x8d, 0xef, 0x24, 0x56, 0x6d, 0xba, 0x49, 0xd4, + 0x8b, 0xb5, 0xa0, 0xb1, 0xc9, 0x8c, 0x32, 0x95, 0x1c, 0x5e, 0x0a, 0x4b, + 0xf6, 0x00, 0x50, 0x0a, 0x87, 0x99, 0x59, 0xcf, 0x6f, 0x9d, 0x02, 0xd0, + 0x1b, 0xa1, 0x96, 0x45, 0x28, 0x76, 0x40, 0x33, 0x28, 0xc9, 0xa1, 0xfd, + 0x46, 0xab, 0x2c, 0x9e, 0x5e, 0xc6, 0x74, 0x19, 0x9a, 0xf5, 0x9b, 0x51, + 0x11, 0x4f, 0xc8, 0xb9, 0x99, 0x6b, 0x4e, 0x3e, 0x31, 0x64, 0xb4, 0x92, + 0xf4, 0x0d, 0x41, 0x4b, 0x2c, 0x65, 0x23, 0xf7, 0x47, 0xe3, 0xa5, 0x2e, + 0xe4, 0x9c, 0x2b, 0xc9, 0x41, 0x22, 0x83, 0x8a, 0x23, 0xef, 0x29, 0x7e, + 0x4f, 0x3f, 0xa3, 0xbf, 0x73, 0x2b, 0xd7, 0xcc, 0xc8, 0xc6, 0xe9, 0xbc, + 0x01, 0xb7, 0x32, 0x63, 0xd4, 0x7e, 0x7f, 0x9a, 0xaf, 0x5f, 0x05, 0x31, + 0x53, 0xd6, 0x1f, 0xa2, 0xd0, 0xdf, 0x67, 0x56, 0xf1, 0x9c, 0x4a, 0x9d, + 0x83, 0xb4, 0xef, 0xb3, 0xf2, 0xcc, 0xf1, 0x91, 0x6c, 0x47, 0xc3, 0x8b, + 0xd0, 0x92, 0x79, 0x3d, 0xa0, 0xc0, 0x3a, 0x57, 0x26, 0x6d, 0x0a, 0xad, + 0x5f, 0xad, 0xb4, 0x74, 0x48, 0x4a, 0x51, 0xe1, 0xb5, 0x82, 0x0a, 0x4c, + 0x4f, 0x9d, 0xaf, 0xee, 0x5a, 0xa2, 0x4d, 0x4d, 0x5f, 0xe0, 0x17, 0x00, + 0x23, 0x00, 0x00 + }; + byte alert_reply[50]; + byte expected_alert_reply[] = { + 0x15, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x02, 0x2f + }; + + fd = wolfSSL_get_fd(ssl); + ret = (int)send(fd, ch_msh_invalid_cookie, sizeof(ch_msh_invalid_cookie), 0); + AssertIntGT(ret, 0); + /* should reply with an illegal_parameter reply */ + ret = (int)recv(fd, alert_reply, sizeof(alert_reply), 0); + AssertIntEQ(ret, sizeof(expected_alert_reply)); + AssertIntEQ(XMEMCMP(alert_reply, expected_alert_reply, sizeof(expected_alert_reply)), 0); +} +#endif + +static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(WOLFSSL* ssl) +{ +#ifndef NO_MD5 + enum wc_HashType hashType = WC_HASH_TYPE_MD5; +#elif !defined(NO_SHA) + enum wc_HashType hashType = WC_HASH_TYPE_SHA; +#elif !defined(NO_SHA256) + enum wc_HashType hashType = WC_HASH_TYPE_SHA256; +#else + #error "We need a digest to hash the WOLFSSL object" +#endif + byte hashBuf[WC_MAX_DIGEST_SIZE]; + wc_HashAlg hash; + TLSX* exts = ssl->extensions; + WOLFSSL sslCopy; /* Use a copy to omit certain fields */ + HS_Hashes* hsHashes = ssl->hsHashes; /* Is re-allocated in + * InitHandshakeHashes */ + + XMEMCPY(&sslCopy, ssl, sizeof(*ssl)); + XMEMSET(hashBuf, 0, sizeof(hashBuf)); + + /* Following fields are not important to compare */ + sslCopy.buffers.inputBuffer.buffer = NULL; + sslCopy.buffers.inputBuffer.bufferSize = 0; + sslCopy.buffers.inputBuffer.dynamicFlag = 0; + sslCopy.error = 0; + sslCopy.curSize = 0; + sslCopy.keys.curSeq_lo = 0; + XMEMSET(&sslCopy.curRL, 0, sizeof(sslCopy.curRL)); +#ifdef WOLFSSL_DTLS13 + XMEMSET(&sslCopy.keys.curSeq, 0, sizeof(sslCopy.keys.curSeq)); + sslCopy.dtls13FastTimeout = 0; +#endif + sslCopy.keys.dtls_peer_handshake_number = 0; + XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history)); + sslCopy.hsHashes = NULL; + + AssertIntEQ(wc_HashInit(&hash, hashType), 0); + AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)&sslCopy, sizeof(sslCopy)), 0); + /* hash extension list */ + while (exts != NULL) { + AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)exts, sizeof(*exts)), 0); + exts = exts->next; + } + /* Hash suites */ + if (sslCopy.suites != NULL) { + AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)sslCopy.suites, + sizeof(struct Suites)), 0); + } + /* Hash hsHashes */ + AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)hsHashes, + sizeof(*hsHashes)), 0); + AssertIntEQ(wc_HashFinal(&hash, hashType, hashBuf), 0); + AssertIntEQ(wc_HashFree(&hash, hashType), 0); + + return MakeWordFromHash(hashBuf); +} + +static void test_wolfSSL_dtls_compare_stateless(WOLFSSL* ssl) +{ + /* Compare the ssl object before and after one ClientHello msg */ + SOCKET_T fd = wolfSSL_get_fd(ssl); + int res; + int err; + word32 initHash; + + wolfSSL_dtls_set_using_nonblock(ssl, 1); + tcp_set_nonblocking(&fd); + + initHash = test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl); + (void)initHash; + + res = tcp_select(fd, 5); + /* We are expecting a msg. A timeout indicates failure. */ + AssertIntEQ(res, TEST_RECV_READY); + + res = wolfSSL_accept(ssl); + err = wolfSSL_get_error(ssl, res); + AssertIntEQ(res, WOLFSSL_FATAL_ERROR); + AssertIntEQ(err, WOLFSSL_ERROR_WANT_READ); + + AssertIntEQ(initHash, test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl)); + + wolfSSL_dtls_set_using_nonblock(ssl, 0); + tcp_set_blocking(&fd); + +} + #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) static void test_wolfSSL_dtls_enable_hrrcookie(WOLFSSL* ssl) { int ret; ret = wolfSSL_send_hrr_cookie(ssl, NULL, 0); AssertIntEQ(ret, WOLFSSL_SUCCESS); + test_wolfSSL_dtls_compare_stateless(ssl); } #endif @@ -59269,10 +59430,12 @@ static int test_wolfSSL_dtls_stateless(void) ssl_callback server_ssl_ready; } test_params[] = { {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, - test_wolfSSL_dtls_send_ch, NULL}, + test_wolfSSL_dtls_send_ch, test_wolfSSL_dtls_compare_stateless}, #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, test_wolfSSL_dtls_send_ch, test_wolfSSL_dtls_enable_hrrcookie}, + {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, + test_wolfSSL_dtls_send_ch_with_invalid_cookie, test_wolfSSL_dtls_enable_hrrcookie}, #endif }; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 3d5181235..a904c6d53 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2123,6 +2123,14 @@ struct Suites { byte setSuites; /* user set suites from default */ }; +typedef struct CipherSuite { + byte cipherSuite0; + byte cipherSuite; + word32 ecdhCurveOID; + struct KeyShareEntry* clientKSE; + int doHelloRetry; +} CipherSuite; + WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, int haveFalconSig, int haveDilithiumSig, int haveAnon, @@ -2140,6 +2148,9 @@ WOLFSSL_LOCAL void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveFalconSig, word16 haveDilithiumSig, word16 haveAnon, word16 haveNull, int side); +typedef struct TLSX TLSX; +WOLFSSL_LOCAL int MatchSuite_ex(const WOLFSSL* ssl, Suites* peerSuites, + CipherSuite* cs, TLSX* extensions); WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list); @@ -2692,10 +2703,17 @@ WOLFSSL_LOCAL int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, WOLFSSL_LOCAL int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, int* found); +/* Forward declare opaque pointer to make available for func def */ +typedef struct Options Options; +WOLFSSL_LOCAL int TLSX_SupportedVersions_Parse(const WOLFSSL* ssl, + const byte* input, word16 length, byte msgType, ProtocolVersion* pv, + Options* opts, TLSX** exts); WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, Suites *suites); WOLFSSL_LOCAL int TLSX_Push(TLSX** list, TLSX_Type type, const void* data, void* heap); +WOLFSSL_LOCAL int TLSX_Append(TLSX** list, TLSX_Type type, + const void* data, void* heap); #elif defined(HAVE_SNI) \ || defined(HAVE_MAX_FRAGMENT) \ @@ -2886,13 +2904,15 @@ WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point, void* heap); #ifndef NO_WOLFSSL_SERVER -WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, - byte second); +WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, + byte second, CipherSuite* cs); WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl); #endif WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported); +WOLFSSL_LOCAL int TLSX_SupportedCurve_Parse(const WOLFSSL* ssl, + const byte* input, word16 length, byte isRequest, TLSX** extensions); #endif /* HAVE_SUPPORTED_CURVES */ @@ -3023,11 +3043,18 @@ int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl); /* Cookie extension information - cookie data. */ typedef struct Cookie { word16 len; - byte data; + /* Ignore "nonstandard extension used : zero-sized array in struct/union" + * MSVC warning */ + #ifdef _MSC_VER + #pragma warning(disable: 4200) + #endif + byte data[]; } Cookie; -WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, const byte* data, word16 len, - byte* mac, byte macSz, int resp); +WOLFSSL_LOCAL int TLSX_Cookie_Use(const WOLFSSL* ssl, const byte* data, + word16 len, byte* mac, byte macSz, int resp, TLSX** exts); +WOLFSSL_LOCAL int TlsCheckCookie(const WOLFSSL* ssl, const byte* cookie, + byte cookieSz); /* Key Share - TLS v1.3 Specification */ @@ -3050,11 +3077,20 @@ typedef struct KeyShareEntry { struct KeyShareEntry* next; /* List pointer */ } KeyShareEntry; -WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, - byte* data, KeyShareEntry **kse); +WOLFSSL_LOCAL int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, + word16 len, byte* data, KeyShareEntry **kse, TLSX** extensions); WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, + TLSX** extensions); +WOLFSSL_LOCAL int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, + KeyShareEntry** kse, byte* searched); +WOLFSSL_LOCAL int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE); WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl, int* doHelloRetry); -WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* sclientKSEclientKSEsl); +WOLFSSL_LOCAL int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte msgType); +WOLFSSL_LOCAL int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl, + const byte* input, word16 length, TLSX** extensions); #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) @@ -3096,7 +3132,9 @@ enum PskKeyExchangeMode { #define WOLFSSL_DEF_PSK_CIPHER TLS_AES_128_GCM_SHA256 #endif -WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes); +WOLFSSL_LOCAL int TLSX_PskKeyModes_Use(WOLFSSL* ssl, byte modes); +WOLFSSL_LOCAL int TLSX_PskKeyModes_Parse_Modes(const byte* input, word16 length, + byte msgType, byte* modes); #ifdef WOLFSSL_EARLY_DATA WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max, int is_response); @@ -3804,7 +3842,7 @@ typedef struct Hashes { #endif } Hashes; -WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); +WOLFSSL_LOCAL int BuildCertHashes(const WOLFSSL* ssl, Hashes* hashes); #ifdef WOLFSSL_TLS13 typedef union Digest { @@ -3888,6 +3926,16 @@ typedef struct TicketNonce { #endif +#ifdef WOLFSSL_DTLS +typedef struct PskInfo { + ProtocolVersion pv; + byte cipherSuite0; + byte cipherSuite; + word16 namedGroup; + byte isValid:1; +} PskInfo; +#endif + /* wolfSSL session type */ struct WOLFSSL_SESSION { /* WARNING Do not add fields here. They will be ignored in @@ -4221,6 +4269,7 @@ typedef struct Options { word16 tls1_1:1; /* using TLSv1.1+ ? */ word16 tls1_3:1; /* using TLSv1.3+ ? */ word16 dtls:1; /* using datagrams ? */ + word16 dtlsStateful:1; /* allow stateful processing ? */ word16 connReset:1; /* has the peer reset */ word16 isClosed:1; /* if we consider conn closed */ word16 closeNotify:1; /* we've received a close notify */ @@ -5625,6 +5674,8 @@ WOLFSSL_LOCAL int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr); WOLFSSL_LOCAL const char* AlertTypeToString(int type); WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL* ssl); +WOLFSSL_LOCAL int SetCipherSpecs_ex(word16 side, byte cipherSuite0, + byte cipherSuite, CipherSpecs* specs, Options* opts); WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL* ssl); WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); @@ -5640,7 +5691,8 @@ WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); -WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); +WOLFSSL_LOCAL int VerifyClientSuite(word16 havePSK, byte cipherSuite0, + byte cipherSuite); WOLFSSL_LOCAL int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length); WOLFSSL_LOCAL int wolfSSL_GetMaxFragSize(WOLFSSL* ssl, int maxFragment); @@ -5656,7 +5708,8 @@ WOLFSSL_LOCAL int SetECKeyExternal(WOLFSSL_EC_KEY* eckey); #endif #if defined(OPENSSL_EXTRA) -WOLFSSL_LOCAL int wolfSSL_curve_is_disabled(WOLFSSL* ssl, word16 named_curve); +WOLFSSL_LOCAL int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, + word16 named_curve); #else #define wolfSSL_curve_is_disabled(ssl, c) ((void)(ssl), (void)(c), 0) #endif @@ -5803,8 +5856,8 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); const byte* cookie, byte cookieSz); #if !defined(NO_WOLFSSL_SERVER) - WOLFSSL_LOCAL int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, - word32* inOutIdx, word32 helloSz, byte *process); + WOLFSSL_LOCAL int DoClientHelloStateless(WOLFSSL* ssl, + const byte* input, word32* inOutIdx, word32 helloSz); #endif /* !defined(NO_WOLFSSL_SERVER) */ #endif /* WOLFSSL_DTLS */ @@ -5816,6 +5869,7 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); #endif WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); WOLFSSL_LOCAL int IsDtlsNotSctpMode(WOLFSSL* ssl); + WOLFSSL_LOCAL int IsDtlsNotSrtpMode(WOLFSSL* ssl); WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); diff --git a/wolfssl/test.h b/wolfssl/test.h index aa18aaeeb..18419975d 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -2288,6 +2288,27 @@ static WC_INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) #endif } +static WC_INLINE void tcp_set_blocking(SOCKET_T* sockfd) +{ + #ifdef USE_WINDOWS_API + unsigned long blocking = 0; + int ret = ioctlsocket(*sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + err_sys_with_errno("ioctlsocket failed"); + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \ + || defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) \ + || defined(WOLFSSL_ZEPHYR) + /* non blocking not supported, for now */ + #else + int flags = fcntl(*sockfd, F_GETFL, 0); + if (flags < 0) + err_sys_with_errno("fcntl get failed"); + flags = fcntl(*sockfd, F_SETFL, flags & (~O_NONBLOCK)); + if (flags < 0) + err_sys_with_errno("fcntl set failed"); + #endif +} + #ifndef NO_PSK From 7dfa96a7290fa41e7d55ba15277150d896768d8f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 30 Dec 2022 16:26:39 +0100 Subject: [PATCH 02/29] Define `usePSK` when ext is present --- src/dtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index b9c683a3c..ba946ce8f 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -557,10 +557,10 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); doKE = 1; } - else { - if ((modes & (1 << PSK_KE)) == 0) + else if ((modes & (1 << PSK_KE)) == 0) { ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); } + usePSK = 1; } #endif From 6160f93f94f317be10d6653bdc352efda4305e47 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 2 Jan 2023 16:48:07 +0100 Subject: [PATCH 03/29] Fix Jenkins errors --- src/dtls.c | 12 +++++++++++- wolfssl/internal.h | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/dtls.c b/src/dtls.c index ba946ce8f..6fa691bba 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -296,7 +296,9 @@ static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, if (ret != WOLFSSL_TICKET_RET_OK && ret != WOLFSSL_TICKET_RET_CREATE) return 0; /* Store info for later */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) pskInfo->pv = it->pv; +#endif pskInfo->cipherSuite0 = it->suite[0]; pskInfo->cipherSuite = it->suite[1]; ato16(it->namedGroup, &pskInfo->namedGroup); @@ -344,7 +346,9 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID ret = TlsSessionCacheGetAndLock(sessionID.elements, &sess, &sessRow, 1); if (ret == 0 && sess != NULL) { /* Store info for later */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) pskInfo->pv = sess->version; +#endif pskInfo->cipherSuite0 = sess->cipherSuite0; pskInfo->cipherSuite = sess->cipherSuite; pskInfo->namedGroup = sess->namedGroup; @@ -381,6 +385,8 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, int ret; ProtocolVersion pv = ssl->version; + (void)pskInfo; + ret = TlsxFindByType(&tlsxSupportedVersions, TLSX_SUPPORTED_VERSIONS, ch->extension); if (ret != 0) @@ -393,9 +399,11 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, tlsxSupportedVersions.size, client_hello, &pv, NULL, NULL); if (ret != 0) return ret; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) if (pskInfo->isValid && (pskInfo->pv.major != pv.major || pskInfo->pv.minor != pv.minor)) return VERSION_ERROR; +#endif if (IsAtLeastTLSv1_3(pv)) *isTls13 = 1; else @@ -633,9 +641,11 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, nonConstSSL->options.cipherSuite = cs.cipherSuite; nonConstSSL->extensions = parsedExts; - ret = SendTls13ServerHello(nonConstSSL, hello_retry_request); + /* Can be modified inside SendTls13ServerHello */ + parsedExts = nonConstSSL->extensions; + InitCipherSpecs(&nonConstSSL->specs); nonConstSSL->session->sessionIDSz = 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a904c6d53..5bb6c3c31 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3928,7 +3928,10 @@ typedef struct TicketNonce { #ifdef WOLFSSL_DTLS typedef struct PskInfo { +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + /* Macro guard matches one for session->version */ ProtocolVersion pv; +#endif byte cipherSuite0; byte cipherSuite; word16 namedGroup; From a999909969e794966ca8ad6641c0ec8ee291dbef Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 3 Jan 2023 17:05:12 +0100 Subject: [PATCH 04/29] Use PSK callback to get the ciphersuite to use - Allocate additional byte in TLSX_PreSharedKey_New for null terminator --- src/dtls.c | 105 ++++++++++++++-------- src/tls.c | 219 ++++++++++++++++++++++++--------------------- src/tls13.c | 103 +++++++++++---------- wolfssl/internal.h | 13 ++- 4 files changed, 255 insertions(+), 185 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 6fa691bba..95ec7f517 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -435,6 +435,38 @@ static int CopyExtensions(TLSX* src, TLSX** dst, void* heap) } #endif +#if defined(WOLFSSL_DTLS13) && !defined(NO_PSK) +/* Very simplified version of CheckPreSharedKeys to find the current suite */ +static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, + PskInfo* pskInfo, Suites* suites) +{ + TLSX* pskExt = TLSX_Find(extensions, TLSX_PRE_SHARED_KEY); + int found = 0; + PreSharedKey* current; + byte psk_key[MAX_PSK_KEY_LEN]; + word32 psk_keySz; + int i; + + if (pskExt == NULL) + return; + + for (i = 0; i < suites->suiteSz; i += 2) { + for (current = (PreSharedKey*)pskExt->data; current != NULL; + current = current->next) { + if (FindPskSuite(ssl, current, psk_key, &psk_keySz, + suites->suites + i, &found) == 0) { + if (found) { + pskInfo->cipherSuite0 = suites->suites[i]; + pskInfo->cipherSuite = suites->suites[i + 1]; + pskInfo->isValid = 1; + return; + } + } + } + } +} +#endif + static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, PskInfo* pskInfo) { @@ -550,39 +582,46 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, * and if they don't match we will error out there anyway. */ byte modes; - ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size == 0) - ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); - ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, - client_hello, &modes); - if (ret != 0) - goto dtls13_cleanup; - if ((modes & (1 << PSK_DHE_KE)) && !ssl->options.noPskDheKe) { - if (!haveKS) +#ifndef NO_PSK + /* When we didn't find a valid ticket ask the user for the + * ciphersuite matching this identity */ + if (!pskInfo->isValid) { + if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, + tlsx.elements, tlsx.size, ssl->heap) == 0) + FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites); + /* Revert to full handshake if PSK parsing failed */ + } +#endif + + if (pskInfo->isValid) { + ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size == 0) ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); - doKE = 1; + ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, + client_hello, &modes); + if (ret != 0) + goto dtls13_cleanup; + if ((modes & (1 << PSK_DHE_KE)) && + !ssl->options.noPskDheKe) { + if (!haveKS) + ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); + doKE = 1; + } + else if ((modes & (1 << PSK_KE)) == 0) { + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + } + usePSK = 1; } - else if ((modes & (1 << PSK_KE)) == 0) { - ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); - } - usePSK = 1; } #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (usePSK) { - if (pskInfo->isValid) { - cs.cipherSuite0 = pskInfo->cipherSuite0; - cs.cipherSuite = pskInfo->cipherSuite; - } - else { - /* Only support the default ciphersuite for PSK */ - cs.cipherSuite0 = TLS13_BYTE; - cs.cipherSuite = WOLFSSL_DEF_PSK_CIPHER; - } + if (usePSK && pskInfo->isValid) { + cs.cipherSuite0 = pskInfo->cipherSuite0; + cs.cipherSuite = pskInfo->cipherSuite; if (doKE) { byte searched = 0; @@ -609,15 +648,9 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, if (ret != 0) goto dtls13_cleanup; } - - /* Need to remove the keyshare ext if we are not doing PSK and we - * found a common group. */ - if (cs.clientKSE != NULL -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - && !usePSK -#endif - ) - { + else { + /* Need to remove the keyshare ext if we found a common group + * and are not doing curve negotiation. */ TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); } diff --git a/src/tls.c b/src/tls.c index 815da07cf..6f15edbf9 100644 --- a/src/tls.c +++ b/src/tls.c @@ -9503,6 +9503,100 @@ static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, return 0; } +int TLSX_PreSharedKey_Parse_ClientHello(TLSX** extensions, const byte* input, + word16 length, void* heap) +{ + + int ret; + word16 len; + word16 idx = 0; + TLSX* extension; + PreSharedKey* list; + + TLSX_Remove(extensions, TLSX_PRE_SHARED_KEY, heap); + + /* Length of identities and of binders. */ + if ((int)(length - idx) < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identities. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_ID_LEN || length - idx < len) + return BUFFER_E; + + /* Create a pre-shared key object for each identity. */ + while (len > 0) { + const byte* identity; + word16 identityLen; + word32 age; + + if (len < OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identity. */ + ato16(input + idx, &identityLen); + idx += OPAQUE16_LEN; + if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN || + identityLen > MAX_PSK_ID_LEN) + return BUFFER_E; + /* Cache identity pointer. */ + identity = input + idx; + idx += identityLen; + /* Ticket age. */ + ato32(input + idx, &age); + idx += OPAQUE32_LEN; + + ret = TLSX_PreSharedKey_Use(extensions, identity, identityLen, age, no_mac, + 0, 0, 1, NULL, heap); + if (ret != 0) + return ret; + + /* Done with this identity. */ + len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN; + } + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Length of binders. */ + if (idx + OPAQUE16_LEN > length) + return BUFFER_E; + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_BINDERS_LEN || length - idx < len) + return BUFFER_E; + + /* Set binder for each identity. */ + while (list != NULL && len > 0) { + /* Length of binder */ + list->binderLen = input[idx++]; + if (list->binderLen < WC_SHA256_DIGEST_SIZE || + list->binderLen > WC_MAX_DIGEST_SIZE) + return BUFFER_E; + if (len < OPAQUE8_LEN + list->binderLen) + return BUFFER_E; + + /* Copy binder into static buffer. */ + XMEMCPY(list->binder, input + idx, list->binderLen); + idx += (word16)list->binderLen; + + /* Done with binder entry. */ + len -= OPAQUE8_LEN + (word16)list->binderLen; + + /* Next identity. */ + list = list->next; + } + if (list != NULL || len != 0) + return BUFFER_E; + + return 0; + +} + /* Parse the pre-shared key extension. * Different formats in different messages. * @@ -9519,91 +9613,8 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, const byte* input, PreSharedKey* list; if (msgType == client_hello) { - int ret; - word16 len; - word16 idx = 0; - - TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); - - /* Length of identities and of binders. */ - if ((int)(length - idx) < OPAQUE16_LEN + OPAQUE16_LEN) - return BUFFER_E; - - /* Length of identities. */ - ato16(input + idx, &len); - idx += OPAQUE16_LEN; - if (len < MIN_PSK_ID_LEN || length - idx < len) - return BUFFER_E; - - /* Create a pre-shared key object for each identity. */ - while (len > 0) { - const byte* identity; - word16 identityLen; - word32 age; - - if (len < OPAQUE16_LEN) - return BUFFER_E; - - /* Length of identity. */ - ato16(input + idx, &identityLen); - idx += OPAQUE16_LEN; - if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN || - identityLen > MAX_PSK_ID_LEN) - return BUFFER_E; - /* Cache identity pointer. */ - identity = input + idx; - idx += identityLen; - /* Ticket age. */ - ato32(input + idx, &age); - idx += OPAQUE32_LEN; - - ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac, - 0, 0, 1, NULL); - if (ret != 0) - return ret; - - /* Done with this identity. */ - len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN; - } - - /* Find the list of identities sent to server. */ - extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); - if (extension == NULL) - return PSK_KEY_ERROR; - list = (PreSharedKey*)extension->data; - - /* Length of binders. */ - if (idx + OPAQUE16_LEN > length) - return BUFFER_E; - ato16(input + idx, &len); - idx += OPAQUE16_LEN; - if (len < MIN_PSK_BINDERS_LEN || length - idx < len) - return BUFFER_E; - - /* Set binder for each identity. */ - while (list != NULL && len > 0) { - /* Length of binder */ - list->binderLen = input[idx++]; - if (list->binderLen < WC_SHA256_DIGEST_SIZE || - list->binderLen > WC_MAX_DIGEST_SIZE) - return BUFFER_E; - if (len < OPAQUE8_LEN + list->binderLen) - return BUFFER_E; - - /* Copy binder into static buffer. */ - XMEMCPY(list->binder, input + idx, list->binderLen); - idx += (word16)list->binderLen; - - /* Done with binder entry. */ - len -= OPAQUE8_LEN + (word16)list->binderLen; - - /* Next identity. */ - list = list->next; - } - if (list != NULL || len != 0) - return BUFFER_E; - - return 0; + return TLSX_PreSharedKey_Parse_ClientHello(&ssl->extensions, input, + length, ssl->heap); } if (msgType == server_hello) { @@ -9675,13 +9686,16 @@ static int TLSX_PreSharedKey_New(PreSharedKey** list, const byte* identity, XMEMSET(psk, 0, sizeof(*psk)); /* Make a copy of the identity data. */ - psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX); + psk->identity = (byte*)XMALLOC(len + NULL_TERM_LEN, heap, + DYNAMIC_TYPE_TLSX); if (psk->identity == NULL) { XFREE(psk, heap, DYNAMIC_TYPE_TLSX); return MEMORY_E; } XMEMCPY(psk->identity, identity, len); psk->identityLen = len; + /* Use a NULL terminator in case it is a C string */ + psk->identity[psk->identityLen] = '\0'; /* Add it to the end and maintain the links. */ while (*list != NULL) { @@ -9729,24 +9743,24 @@ static WC_INLINE byte GetHmacLength(int hmac) * preSharedKey The new pre-shared key object. * returns 0 on success and other values indicate failure. */ -int TLSX_PreSharedKey_Use(WOLFSSL* ssl, const byte* identity, word16 len, +int TLSX_PreSharedKey_Use(TLSX** extensions, const byte* identity, word16 len, word32 age, byte hmac, byte cipherSuite0, byte cipherSuite, byte resumption, - PreSharedKey **preSharedKey) + PreSharedKey **preSharedKey, void* heap) { int ret = 0; TLSX* extension; PreSharedKey* psk = NULL; /* Find the pre-shared key extension if it exists. */ - extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY); if (extension == NULL) { /* Push new pre-shared key extension. */ - ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap); + ret = TLSX_Push(extensions, TLSX_PRE_SHARED_KEY, NULL, heap); if (ret != 0) return ret; - extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY); if (extension == NULL) return MEMORY_E; } @@ -9764,7 +9778,7 @@ int TLSX_PreSharedKey_Use(WOLFSSL* ssl, const byte* identity, word16 len, /* Create a new pre-shared key object if not found. */ if (psk == NULL) { ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity, - len, ssl->heap, &psk); + len, heap, &psk); if (ret != 0) return ret; } @@ -12026,17 +12040,18 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) milli += sess->ticketAdd; /* Pre-shared key is mandatory extension for resumption. */ - ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, - milli, ssl->specs.mac_algorithm, ssl->options.cipherSuite0, - ssl->options.cipherSuite, 1, NULL); + ret = TLSX_PreSharedKey_Use(&ssl->extensions, sess->ticket, + sess->ticketLen, milli, ssl->specs.mac_algorithm, + ssl->options.cipherSuite0, ssl->options.cipherSuite, 1, + NULL, ssl->heap); #else milli = now - sess->ticketSeen + sess->ticketAdd; /* Pre-shared key is mandatory extension for resumption. */ - ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, - (word32)milli, ssl->specs.mac_algorithm, + ret = TLSX_PreSharedKey_Use(&ssl->extensions, sess->ticket, + sess->ticketLen, (word32)milli, ssl->specs.mac_algorithm, ssl->options.cipherSuite0, ssl->options.cipherSuite, 1, - NULL); + NULL, ssl->heap); #endif if (ret != 0) return ret; @@ -12083,11 +12098,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) GetCipherNameInternal(cipherSuite0, cipherSuite)); if (keySz > 0) { ssl->arrays->psk_keySz = keySz; - ret = TLSX_PreSharedKey_Use(ssl, + ret = TLSX_PreSharedKey_Use(&ssl->extensions, (byte*)ssl->arrays->client_identity, (word16)XSTRLEN(ssl->arrays->client_identity), 0, SuiteMac(WOLFSSL_SUITES(ssl)->suites + i), - cipherSuite0, cipherSuite, 0, NULL); + cipherSuite0, cipherSuite, 0, NULL, ssl->heap); if (ret != 0) return ret; #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS @@ -12150,12 +12165,12 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (ret != 0) return ret; - ret = TLSX_PreSharedKey_Use(ssl, + ret = TLSX_PreSharedKey_Use(&ssl->extensions, (byte*)ssl->arrays->client_identity, (word16)XSTRLEN(ssl->arrays->client_identity), 0, ssl->specs.mac_algorithm, cipherSuite0, cipherSuite, 0, - NULL); + NULL, ssl->heap); if (ret != 0) return ret; diff --git a/src/tls13.c b/src/tls13.c index fd418f7d1..c5c61f5f3 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5496,6 +5496,60 @@ static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) #ifndef NO_PSK +int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, + word32* psk_keySz, byte* suite, int* found) +{ + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + int ret = 0; + + *found = 0; + (void)suite; + + if (ssl->options.server_psk_tls13_cb != NULL) { + *psk_keySz = ssl->options.server_psk_tls13_cb((WOLFSSL*)ssl, + (char*)psk->identity, psk_key, MAX_PSK_KEY_LEN, &cipherName); + if (*psk_keySz != 0) { + int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE; + *found = (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite, &cipherSuiteFlags) == 0); + (void)cipherSuiteFlags; + } + } + if (*found == 0 && (ssl->options.server_psk_cb != NULL)) { + *psk_keySz = ssl->options.server_psk_cb((WOLFSSL*)ssl, + (char*)psk->identity, psk_key, + MAX_PSK_KEY_LEN); + *found = (*psk_keySz != 0); + } + if (*found) { + if (*psk_keySz > MAX_PSK_KEY_LEN) { + WOLFSSL_MSG("Key len too long in FindPsk()"); + ret = PSK_KEY_ERROR; + WOLFSSL_ERROR_VERBOSE(ret); + } + if (ret == 0) { + #if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK) + /* Check whether PSK ciphersuite is in SSL. */ + *found = (suite[0] == cipherSuite0) && (suite[1] == cipherSuite); + #else + (void)suite; + /* Check whether PSK ciphersuite is in SSL. */ + { + byte s[2] = { + cipherSuite0, + cipherSuite, + }; + *found = FindSuiteSSL(ssl, s); + } + #endif + } + } + + return ret; +} + /* Attempt to find the PSK (not session ticket) that matches. * * @param [in, out] ssl The SSL/TLS object. @@ -5509,55 +5563,14 @@ static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) * @return 1 when a match found - but check error code. * @return 0 when no match found. */ -static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err) +static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) { int ret = 0; int found = 0; - const char* cipherName = NULL; - byte cipherSuite0 = TLS13_BYTE; - byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; - Arrays* sa = ssl->arrays; - (void)suite; - - if (ssl->options.server_psk_tls13_cb != NULL) { - sa->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, - sa->client_identity, sa->psk_key, MAX_PSK_KEY_LEN, &cipherName); - if (sa->psk_keySz != 0) { - int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE; - found = (GetCipherSuiteFromName(cipherName, &cipherSuite0, - &cipherSuite, &cipherSuiteFlags) == 0); - (void)cipherSuiteFlags; - } - } - if (!found && (ssl->options.server_psk_cb != NULL)) { - sa->psk_keySz = ssl->options.server_psk_cb(ssl, - sa->client_identity, sa->psk_key, - MAX_PSK_KEY_LEN); - found = (sa->psk_keySz != 0); - } - if (found) { - if (sa->psk_keySz > MAX_PSK_KEY_LEN) { - WOLFSSL_MSG("Key len too long in FindPsk"); - ret = PSK_KEY_ERROR; - WOLFSSL_ERROR_VERBOSE(ret); - } - if (ret == 0) { - #if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK) - /* Check whether PSK ciphersuite is in SSL. */ - found = (suite[0] == cipherSuite0) && (suite[1] == cipherSuite); - #else - (void)suite; - /* Check whether PSK ciphersuite is in SSL. */ - { - byte s[2] = { - cipherSuite0, - cipherSuite, - }; - found = FindSuiteSSL(ssl, s); - } - #endif - } + ret = FindPskSuite(ssl, psk, ssl->arrays->psk_key, &ssl->arrays->psk_keySz, + suite, &found); + if (ret == 0 && found) { if ((ret == 0) && found) { /* Default to ciphersuite if cb doesn't specify. */ ssl->options.resuming = 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 5bb6c3c31..c7bc10c57 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3115,11 +3115,14 @@ WOLFSSL_LOCAL int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, word16* pSz); WOLFSSL_LOCAL int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType, word16* pSz); -WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, const byte* identity, +WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(TLSX** extensions, const byte* identity, word16 len, word32 age, byte hmac, byte cipherSuite0, byte cipherSuite, byte resumption, - PreSharedKey **preSharedKey); + PreSharedKey **preSharedKey, + void* heap); +WOLFSSL_LOCAL int TLSX_PreSharedKey_Parse_ClientHello(TLSX** extensions, + const byte* input, word16 length, void* heap); /* The possible Pre-Shared Key key exchange modes. */ enum PskKeyExchangeMode { @@ -6204,6 +6207,12 @@ WOLFSSL_LOCAL int wolfSSL_quic_keys_active(WOLFSSL* ssl, enum encrypt_side side) #define WOLFSSL_IS_QUIC(s) 0 #endif /* WOLFSSL_QUIC (else) */ + +#ifndef NO_PSK +WOLFSSL_LOCAL int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, + byte* psk_key, word32* psk_keySz, byte* suite, int* found); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif From aa9dcca624336ee7221bc0f09f927fe9bad5d90f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 19 Jan 2023 13:22:50 +0100 Subject: [PATCH 05/29] Rebase and Jenkins fixes --- src/dtls.c | 24 ++++++++++++++---------- src/dtls13.c | 12 ++++++++---- src/internal.c | 21 +++++++++++++++++---- src/tls.c | 11 +++-------- src/tls13.c | 31 ++++++++++++++++++------------- tests/api.c | 21 +++++++++++++++++++-- wolfssl/internal.h | 9 ++++++--- 7 files changed, 85 insertions(+), 44 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 95ec7f517..6babe3116 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -190,7 +190,7 @@ static int CheckDtlsCookie(const WOLFSSL* ssl, WolfSSL_CH* ch, if (ch->cookie.size - OPAQUE16_LEN != len) return BUFFER_E; ret = TlsCheckCookie(ssl, ch->cookie.elements + OPAQUE16_LEN, - ch->cookie.size - OPAQUE16_LEN); + (word16)(ch->cookie.size - OPAQUE16_LEN)); if (ret < 0 && ret != HRR_COOKIE_ERROR) return ret; *cookieGood = ret > 0; @@ -329,7 +329,9 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID &unused); if (sess != NULL) { /* Store info for later */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) pskInfo->pv = sess->version; +#endif pskInfo->cipherSuite0 = sess->cipherSuite0; pskInfo->cipherSuite = sess->cipherSuite; pskInfo->namedGroup = sess->namedGroup; @@ -396,7 +398,7 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, return 0; } ret = TLSX_SupportedVersions_Parse(ssl, tlsxSupportedVersions.elements, - tlsxSupportedVersions.size, client_hello, &pv, NULL, NULL); + (word16)tlsxSupportedVersions.size, client_hello, &pv, NULL, NULL); if (ret != 0) return ret; #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) @@ -446,6 +448,7 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, byte psk_key[MAX_PSK_KEY_LEN]; word32 psk_keySz; int i; + byte foundSuite[SUITE_LEN]; if (pskExt == NULL) return; @@ -454,10 +457,10 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, for (current = (PreSharedKey*)pskExt->data; current != NULL; current = current->next) { if (FindPskSuite(ssl, current, psk_key, &psk_keySz, - suites->suites + i, &found) == 0) { + suites->suites + i, &found, foundSuite) == 0) { if (found) { - pskInfo->cipherSuite0 = suites->suites[i]; - pskInfo->cipherSuite = suites->suites[i + 1]; + pskInfo->cipherSuite0 = foundSuite[0]; + pskInfo->cipherSuite = foundSuite[1]; pskInfo->isValid = 1; return; } @@ -499,13 +502,14 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, } /* Hashes are reset in SendTls13ServerHello when sending a HRR */ - ret = Dtls13HashHandshake((WOLFSSL*)ssl, ch->msg, ch->length); + ret = Dtls13HashHandshake((WOLFSSL*)ssl, ch->msg, + (word16)ch->length); if (ret != 0) goto dtls13_cleanup; /* Populate the suites struct to find a common ciphersuite */ XMEMSET(&suites, 0, sizeof(suites)); - suites.suiteSz = ch->cipherSuite.size; + suites.suiteSz = (word16)ch->cipherSuite.size; if ((suites.suiteSz % 2) != 0) ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); if (suites.suiteSz > WOLFSSL_MAX_SUITE_SZ) @@ -551,7 +555,7 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, goto dtls13_cleanup; if (tlsx.size != 0) { ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, - tlsx.size, 1, &parsedExts); + (word16)tlsx.size, 1, &parsedExts); if (ret != 0) goto dtls13_cleanup; } @@ -563,7 +567,7 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, goto dtls13_cleanup; if (tlsx.size != 0) { ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, - tlsx.size, &parsedExts); + (word16)tlsx.size, &parsedExts); if (ret != 0) goto dtls13_cleanup; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) @@ -669,7 +673,7 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, ch->sessionId.size); - nonConstSSL->session->sessionIDSz = ch->sessionId.size; + nonConstSSL->session->sessionIDSz = (byte)ch->sessionId.size; nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; nonConstSSL->options.cipherSuite = cs.cipherSuite; nonConstSSL->extensions = parsedExts; diff --git a/src/dtls13.c b/src/dtls13.c index 73944a716..a6b63b1a2 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -123,6 +123,7 @@ WOLFSSL_METHOD* wolfDTLSv1_3_client_method_ex(void* heap) WOLFSSL_METHOD* method; WOLFSSL_ENTER("DTLSv1_3_client_method_ex"); + (void)heap; method = (WOLFSSL_METHOD*)XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); @@ -145,6 +146,7 @@ WOLFSSL_METHOD* wolfDTLSv1_3_server_method_ex(void* heap) WOLFSSL_METHOD* method; WOLFSSL_ENTER("DTLSv1_3_server_method_ex"); + (void)heap; method = (WOLFSSL_METHOD*)XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); @@ -613,12 +615,14 @@ static void Dtls13RtxFlushBuffered(WOLFSSL* ssl, byte keepNewSessionTicket) ssl->dtls13Rtx.rtxRecordTailPtr = prevNext; } -static Dtls13RecordNumber* Dtls13NewRecordNumber(WOLFSSL* ssl, w64wrapper epoch, - w64wrapper seq) +static Dtls13RecordNumber* Dtls13NewRecordNumber(w64wrapper epoch, + w64wrapper seq, void* heap) { Dtls13RecordNumber* rn; - rn = (Dtls13RecordNumber*)XMALLOC(sizeof(*rn), ssl->heap, + (void)heap; + + rn = (Dtls13RecordNumber*)XMALLOC(sizeof(*rn), heap, DYNAMIC_TYPE_DTLS_MSG); if (rn == NULL) return NULL; @@ -636,7 +640,7 @@ static int Dtls13RtxAddAck(WOLFSSL* ssl, w64wrapper epoch, w64wrapper seq) WOLFSSL_ENTER("Dtls13RtxAddAck"); - rn = Dtls13NewRecordNumber(ssl, epoch, seq); + rn = Dtls13NewRecordNumber(epoch, seq, ssl->heap); if (rn == NULL) return MEMORY_E; diff --git a/src/internal.c b/src/internal.c index 8f1564cc4..bf91fd546 100644 --- a/src/internal.c +++ b/src/internal.c @@ -32544,8 +32544,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * Returns 1 for valid server suite or 0 if not found * For asynchronous this can return WC_PENDING_E */ - static int VerifyServerSuite(WOLFSSL* ssl, const Suites* suites, word16 idx, - CipherSuite* cs, TLSX* extensions) + static int VerifyServerSuite(const WOLFSSL* ssl, const Suites* suites, + word16 idx, CipherSuite* cs, TLSX* extensions) { #ifndef NO_PSK int havePSK = ssl->options.havePSK; @@ -32553,6 +32553,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte first; byte second; + (void)cs; + (void)extensions; + WOLFSSL_ENTER("VerifyServerSuite"); if (suites == NULL) { @@ -32743,13 +32746,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMSET(&cs, 0, sizeof(cs)); - ret = MatchSuite_ex(ssl, peerSuites, &cs, ssl->extensions); + ret = MatchSuite_ex(ssl, peerSuites, &cs, +#ifdef HAVE_TLS_EXTENSIONS + ssl->extensions +#else + NULL +#endif + ); if (ret != 0) return ret; ssl->options.cipherSuite0 = cs.cipherSuite0; ssl->options.cipherSuite = cs.cipherSuite; +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_CURVE25519) || \ + defined(HAVE_ED448) || defined(HAVE_CURVE448) ssl->ecdhCurveOID = cs.ecdhCurveOID; +#endif ret = SetCipherSpecs(ssl); if (ret != 0) @@ -32759,10 +32771,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (cs.doHelloRetry) { ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions); } +#endif #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (IsAtLeastTLSv1_3(ssl->version) && @@ -33144,7 +33158,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Update the ssl->options.dtlsStateful setting `if` statement in * wolfSSL_accept when changing this one. */ if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl)) { - byte process = 0; if (((ssl->keys.dtls_sequence_number_hi == ssl->keys.curSeq_hi && ssl->keys.dtls_sequence_number_lo < ssl->keys.curSeq_lo) || (ssl->keys.dtls_sequence_number_hi < ssl->keys.curSeq_hi))) { diff --git a/src/tls.c b/src/tls.c index 6f15edbf9..46027e7f7 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1407,15 +1407,10 @@ int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl) #endif -#if defined(WOLFSSL_TLS13) || (!defined(NO_WOLFSSL_SERVER) \ - && (defined(WOLFSSL_SRTP) || defined(HAVE_SESSION_TICKET) \ - || defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO) \ - || defined(HAVE_SUPPORTED_CURVES) || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST) || defined(HAVE_TRUNCATED_HMAC) \ - || defined(HAVE_MAX_FRAGMENT) || defined(HAVE_TRUSTED_CA) || defined(HAVE_SNI) \ - || defined(HAVE_ALPN))) +#if !defined(NO_WOLFSSL_SERVER) || defined(WOLFSSL_TLS13) +void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type); /** Mark an extension to be sent back to the client. */ -static void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) +void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) { TLSX *extension = TLSX_Find(ssl->extensions, type); diff --git a/src/tls13.c b/src/tls13.c index c5c61f5f3..fcce88f52 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3337,7 +3337,7 @@ byte SuiteMac(const byte* suite) * hashSz The size of the hash data in bytes. * returns 0 on success, otherwise failure. */ -static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, byte hashSz, +static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, TLSX** exts) { int ret; @@ -3429,7 +3429,7 @@ static int CreateCookieHash(const WOLFSSL* ssl, byte** hash, byte* hashSz, if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) { byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; TLSX* ext; - word32 idx = 0; + word16 idx = 0; /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ cookie[idx++] = *hashSz; @@ -5497,7 +5497,7 @@ static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) #ifndef NO_PSK int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, - word32* psk_keySz, byte* suite, int* found) + word32* psk_keySz, const byte* suite, int* found, byte* foundSuite) { const char* cipherName = NULL; byte cipherSuite0 = TLS13_BYTE; @@ -5528,6 +5528,7 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, WOLFSSL_MSG("Key len too long in FindPsk()"); ret = PSK_KEY_ERROR; WOLFSSL_ERROR_VERBOSE(ret); + *found = 0; } if (ret == 0) { #if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK) @@ -5546,6 +5547,10 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, #endif } } + if (*found && foundSuite != NULL) { + foundSuite[0] = cipherSuite0; + foundSuite[1] = cipherSuite; + } return ret; } @@ -5563,13 +5568,14 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, * @return 1 when a match found - but check error code. * @return 0 when no match found. */ -static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) +static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, const byte* suite, int* err) { int ret = 0; int found = 0; + byte foundSuite[SUITE_LEN]; ret = FindPskSuite(ssl, psk, ssl->arrays->psk_key, &ssl->arrays->psk_keySz, - suite, &found); + suite, &found, foundSuite); if (ret == 0 && found) { if ((ret == 0) && found) { /* Default to ciphersuite if cb doesn't specify. */ @@ -5585,8 +5591,8 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) } if ((ret == 0) && found) { /* Set PSK ciphersuite into SSL. */ - ssl->options.cipherSuite0 = cipherSuite0; - ssl->options.cipherSuite = cipherSuite; + ssl->options.cipherSuite0 = foundSuite[0]; + ssl->options.cipherSuite = foundSuite[1]; ret = SetCipherSpecs(ssl); } if ((ret == 0) && found) { @@ -6012,7 +6018,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, * cookieSz The length of the cookie data in bytes. * returns Length of the hash on success, otherwise failure. */ -int TlsCheckCookie(const WOLFSSL* ssl, const byte* cookie, byte cookieSz) +int TlsCheckCookie(const WOLFSSL* ssl, const byte* cookie, word16 cookieSz) { int ret; byte mac[WC_MAX_DIGEST_SIZE] = {0}; @@ -6096,14 +6102,15 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) word32 idx; byte hashSz; byte* cookieData; - byte cookieDataSz; + word16 cookieDataSz; word16 length; int keyShareExt = 0; int ret; - cookieDataSz = ret = TlsCheckCookie(ssl, cookie->data, cookie->len); + ret = TlsCheckCookie(ssl, cookie->data, (byte)cookie->len); if (ret < 0) return ret; + cookieDataSz = (word16)ret; hashSz = cookie->data[0]; cookieData = cookie->data; idx = OPAQUE8_LEN; @@ -6206,7 +6213,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { - ret = Dtls13HashHandshake(ssl, hrr, hrrIdx); + ret = Dtls13HashHandshake(ssl, hrr, (word16)hrrIdx); } else #endif /* WOLFSSL_DTLS13 */ @@ -12544,8 +12551,6 @@ static int DtlsAcceptStateless(WOLFSSL *ssl) default: return 0; } - - return 0; } #endif /* WOLFSSL_DTLS13 */ diff --git a/tests/api.c b/tests/api.c index 373beea55..3c0fc66d1 100644 --- a/tests/api.c +++ b/tests/api.c @@ -59346,6 +59346,7 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(WOLFSSL* ssl) sslCopy.buffers.inputBuffer.buffer = NULL; sslCopy.buffers.inputBuffer.bufferSize = 0; sslCopy.buffers.inputBuffer.dynamicFlag = 0; + sslCopy.buffers.inputBuffer.offset = 0; sslCopy.error = 0; sslCopy.curSize = 0; sslCopy.keys.curSeq_lo = 0; @@ -59379,6 +59380,20 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(WOLFSSL* ssl) return MakeWordFromHash(hashBuf); } +static CallbackIORecv test_wolfSSL_dtls_compare_stateless_cb; +static int test_wolfSSL_dtls_compare_stateless_cb_call_once; +static int test_wolfSSL_dtls_compare_stateless_read_cb_once(WOLFSSL *ssl, + char *buf, int sz, void *ctx) +{ + if (test_wolfSSL_dtls_compare_stateless_cb_call_once) { + test_wolfSSL_dtls_compare_stateless_cb_call_once = 0; + return test_wolfSSL_dtls_compare_stateless_cb(ssl, buf, sz, ctx); + } + else { + return WOLFSSL_CBIO_ERR_WANT_READ; + } +} + static void test_wolfSSL_dtls_compare_stateless(WOLFSSL* ssl) { /* Compare the ssl object before and after one ClientHello msg */ @@ -59387,8 +59402,10 @@ static void test_wolfSSL_dtls_compare_stateless(WOLFSSL* ssl) int err; word32 initHash; + test_wolfSSL_dtls_compare_stateless_cb = ssl->CBIORecv; + test_wolfSSL_dtls_compare_stateless_cb_call_once = 1; wolfSSL_dtls_set_using_nonblock(ssl, 1); - tcp_set_nonblocking(&fd); + ssl->CBIORecv = test_wolfSSL_dtls_compare_stateless_read_cb_once; initHash = test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl); (void)initHash; @@ -59405,7 +59422,7 @@ static void test_wolfSSL_dtls_compare_stateless(WOLFSSL* ssl) AssertIntEQ(initHash, test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl)); wolfSSL_dtls_set_using_nonblock(ssl, 0); - tcp_set_blocking(&fd); + ssl->CBIORecv = test_wolfSSL_dtls_compare_stateless_cb; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c7bc10c57..6eb3872e0 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2128,7 +2128,9 @@ typedef struct CipherSuite { byte cipherSuite; word32 ecdhCurveOID; struct KeyShareEntry* clientKSE; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) int doHelloRetry; +#endif } CipherSuite; WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, @@ -3054,7 +3056,7 @@ typedef struct Cookie { WOLFSSL_LOCAL int TLSX_Cookie_Use(const WOLFSSL* ssl, const byte* data, word16 len, byte* mac, byte macSz, int resp, TLSX** exts); WOLFSSL_LOCAL int TlsCheckCookie(const WOLFSSL* ssl, const byte* cookie, - byte cookieSz); + word16 cookieSz); /* Key Share - TLS v1.3 Specification */ @@ -6208,9 +6210,10 @@ WOLFSSL_LOCAL int wolfSSL_quic_keys_active(WOLFSSL* ssl, enum encrypt_side side) #endif /* WOLFSSL_QUIC (else) */ -#ifndef NO_PSK +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) WOLFSSL_LOCAL int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, - byte* psk_key, word32* psk_keySz, byte* suite, int* found); + byte* psk_key, word32* psk_keySz, const byte* suite, int* found, + byte* foundSuite); #endif #ifdef __cplusplus From 2f31cdef69c237abd9d7d60f37cb66698edde15a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 23 Jan 2023 15:54:42 +0100 Subject: [PATCH 06/29] Re-create hs header for hash --- src/dtls.c | 10 +++++----- src/dtls13.c | 31 +++++++++++++++++++++++++------ wolfssl/internal.h | 4 +++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 6babe3116..82be280c0 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -111,7 +111,7 @@ typedef struct WolfSSL_CH { WolfSSL_ConstVector cipherSuite; WolfSSL_ConstVector compression; WolfSSL_ConstVector extension; - const byte* msg; + const byte* raw; word32 length; /* Store the DTLS 1.2 cookie since we can just compute it once in dtls.c */ byte dtls12cookie[DTLS_COOKIE_SZ]; @@ -221,7 +221,7 @@ static int ParseClientHello(const byte* input, word32 helloSz, WolfSSL_CH* ch) if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; - ch->msg = input - DTLS_HANDSHAKE_HEADER_SZ; + ch->raw = input; ch->pv = (ProtocolVersion*)(input + idx); idx += OPAQUE16_LEN; ch->random = (byte*)(input + idx); @@ -241,7 +241,7 @@ static int ParseClientHello(const byte* input, word32 helloSz, WolfSSL_CH* ch) idx += ReadVector16(input + idx, &ch->extension); if (idx > helloSz) return BUFFER_ERROR; - ch->length = idx + DTLS_HANDSHAKE_HEADER_SZ; + ch->length = idx; return 0; } @@ -502,8 +502,8 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, } /* Hashes are reset in SendTls13ServerHello when sending a HRR */ - ret = Dtls13HashHandshake((WOLFSSL*)ssl, ch->msg, - (word16)ch->length); + ret = Dtls13HashHandshakeType((WOLFSSL*)ssl, ch->raw, ch->length, + client_hello); if (ret != 0) goto dtls13_cleanup; diff --git a/src/dtls13.c b/src/dtls13.c index a6b63b1a2..91bddcf8f 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -435,8 +435,27 @@ static int Dtls13SendNow(WOLFSSL* ssl, enum HandShakeType handshakeType) return 0; } -/* Handshake header DTLS only fields are not included in the transcript hash */ -int Dtls13HashHandshake(WOLFSSL* ssl, const byte* output, word16 length) +/* Handshake header DTLS only fields are not inlcuded in the transcript hash. + * body points to the body of the DTLSHandshake message. */ +int Dtls13HashHandshakeType(WOLFSSL* ssl, const byte* body, word32 length, + enum HandShakeType handshakeType) +{ + /* msg_type(1) + length (3) */ + byte header[OPAQUE32_LEN]; + int ret; + + header[0] = (byte)handshakeType; + c32to24(length, header + 1); + + ret = HashRaw(ssl, header, OPAQUE32_LEN); + if (ret != 0) + return ret; + + return HashRaw(ssl, body, length); +} + +/* Handshake header DTLS only fields are not inlcuded in the transcript hash */ +int Dtls13HashHandshake(WOLFSSL* ssl, const byte* input, word16 length) { int ret; @@ -444,18 +463,18 @@ int Dtls13HashHandshake(WOLFSSL* ssl, const byte* output, word16 length) return BAD_FUNC_ARG; /* msg_type(1) + length (3) */ - ret = HashRaw(ssl, output, OPAQUE32_LEN); + ret = HashRaw(ssl, input, OPAQUE32_LEN); if (ret != 0) return ret; - output += OPAQUE32_LEN; + input += OPAQUE32_LEN; length -= OPAQUE32_LEN; /* message_seq(2) + fragment_offset(3) + fragment_length(3) */ - output += OPAQUE64_LEN; + input += OPAQUE64_LEN; length -= OPAQUE64_LEN; - return HashRaw(ssl, output, length); + return HashRaw(ssl, input, length); } static int Dtls13SendFragment(WOLFSSL* ssl, byte* output, word16 output_size, diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 6eb3872e0..add0d2c6f 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -6126,8 +6126,10 @@ WOLFSSL_LOCAL int Dtls13ReconstructSeqNumber(WOLFSSL* ssl, WOLFSSL_LOCAL int SendDtls13Ack(WOLFSSL* ssl); WOLFSSL_LOCAL int Dtls13RtxProcessingCertificate(WOLFSSL* ssl, byte* input, word32 inputSize); -WOLFSSL_LOCAL int Dtls13HashHandshake(WOLFSSL* ssl, const byte* output, +WOLFSSL_LOCAL int Dtls13HashHandshake(WOLFSSL* ssl, const byte* input, word16 length); +WOLFSSL_LOCAL int Dtls13HashHandshakeType(WOLFSSL* ssl, const byte* body, + word32 length, enum HandShakeType handshakeType); WOLFSSL_LOCAL void Dtls13FreeFsmResources(WOLFSSL* ssl); WOLFSSL_LOCAL int Dtls13RtxTimeout(WOLFSSL* ssl); WOLFSSL_LOCAL int Dtls13ProcessBufferedMessages(WOLFSSL* ssl); From c15043b1918ac8fd58f37bdc61c95417081035d3 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 23 Jan 2023 16:06:06 +0100 Subject: [PATCH 07/29] Refactor SendStatelessReply 1.3 branch into new function --- src/dtls.c | 459 +++++++++++++++++++++++++++-------------------------- 1 file changed, 235 insertions(+), 224 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 82be280c0..b5f24f953 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -470,6 +470,240 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, } #endif +#ifdef WOLFSSL_DTLS13 + +#ifndef WOLFSSL_SEND_HRR_COOKIE +#error "WOLFSSL_SEND_HRR_COOKIE has to be defined to use DTLS 1.3 server" +#endif + +static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, + PskInfo* pskInfo) +{ + int ret = -1; + if (ch->cookie.size == 0) { + TLSX* parsedExts = NULL; + WolfSSL_ConstVector tlsx; + Suites suites; + word16 len; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + byte haveKS = 0; + byte usePSK = 0; + byte doKE = 0; +#endif + CipherSuite cs; + CipherSpecs specs; + + XMEMSET(&cs, 0, sizeof(cs)); + XMEMSET(&specs, 0, sizeof(specs)); + + /* We need to echo the session ID sent by the client */ + if (ch->sessionId.size > ID_LEN) { + /* Too large. We can't echo this. */ + ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); + } + + /* Hashes are reset in SendTls13ServerHello when sending a HRR */ + ret = Dtls13HashHandshakeType((WOLFSSL*)ssl, ch->raw, ch->length, + client_hello); + if (ret != 0) + goto dtls13_cleanup; + + /* Populate the suites struct to find a common ciphersuite */ + XMEMSET(&suites, 0, sizeof(suites)); + suites.suiteSz = (word16)ch->cipherSuite.size; + if ((suites.suiteSz % 2) != 0) + ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); + if (suites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + XMEMCPY(suites.suites, ch->cipherSuite.elements, suites.suiteSz); + + /* Populate extensions */ + + /* Supported versions always need to be present. Has to appear after + * key share as that is the order we reconstruct it in + * RestartHandshakeHashWithCookie. */ + ret = TLSX_Push(&parsedExts, + TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); + if (ret != 0) + goto dtls13_cleanup; + /* Set that this is a response extension */ + parsedExts->resp = 1; + + ret = CopyExtensions(ssl->extensions, &parsedExts, ssl->heap); + if (ret != 0) + goto dtls13_cleanup; + + /* Signature algs */ + ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size > OPAQUE16_LEN) { + ato16(tlsx.elements, &len); + if (len != tlsx.size - OPAQUE16_LEN) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + if ((len % 2) != 0) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + suites.hashSigAlgoSz = len; + XMEMCPY(suites.hashSigAlgo, tlsx.elements + OPAQUE16_LEN, + len); + } + + /* Supported groups */ + ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, + (word16)tlsx.size, 1, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; + } + + /* Key share */ + ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, + (word16)tlsx.size, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + haveKS = 1; +#endif + } + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Pre-shared key */ + ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + /* Let's just assume that the binders are correct here. We will + * actually verify this in the stateful part of the processing + * and if they don't match we will error out there anyway. */ + byte modes; + +#ifndef NO_PSK + /* When we didn't find a valid ticket ask the user for the + * ciphersuite matching this identity */ + if (!pskInfo->isValid) { + if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, + tlsx.elements, tlsx.size, ssl->heap) == 0) + FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites); + /* Revert to full handshake if PSK parsing failed */ + } +#endif + + if (pskInfo->isValid) { + ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size == 0) + ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); + ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, + client_hello, &modes); + if (ret != 0) + goto dtls13_cleanup; + if ((modes & (1 << PSK_DHE_KE)) && + !ssl->options.noPskDheKe) { + if (!haveKS) + ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); + doKE = 1; + } + else if ((modes & (1 << PSK_KE)) == 0) { + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + } + usePSK = 1; + } + } +#endif + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (usePSK && pskInfo->isValid) { + cs.cipherSuite0 = pskInfo->cipherSuite0; + cs.cipherSuite = pskInfo->cipherSuite; + + if (doKE) { + byte searched = 0; + ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE, + &searched); + if (ret != 0) + goto dtls13_cleanup; + if (cs.clientKSE == NULL && searched) + cs.doHelloRetry = 1; + } + } + else +#endif + { + ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); + if (ret < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + SendAlert((WOLFSSL*)ssl, alert_fatal, handshake_failure); + goto dtls13_cleanup; + } + } + if (cs.doHelloRetry) { + ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; + } + else { + /* Need to remove the keyshare ext if we found a common group + * and are not doing curve negotiation. */ + TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); + } + + { + WOLFSSL* nonConstSSL = (WOLFSSL*)ssl; + TLSX* sslExts = nonConstSSL->extensions; + + /* This is required to correctly generate the hash */ + ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, + cs.cipherSuite, &nonConstSSL->specs, NULL); + if (ret != 0) + goto dtls13_cleanup; + nonConstSSL->options.tls = 1; + nonConstSSL->options.tls1_1 = 1; + nonConstSSL->options.tls1_3 = 1; + + XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, + ch->sessionId.size); + nonConstSSL->session->sessionIDSz = (byte)ch->sessionId.size; + nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; + nonConstSSL->options.cipherSuite = cs.cipherSuite; + nonConstSSL->extensions = parsedExts; + + ret = SendTls13ServerHello(nonConstSSL, hello_retry_request); + + /* Can be modified inside SendTls13ServerHello */ + parsedExts = nonConstSSL->extensions; + + InitCipherSpecs(&nonConstSSL->specs); + + nonConstSSL->session->sessionIDSz = 0; + nonConstSSL->options.cipherSuite0 = 0; + nonConstSSL->options.cipherSuite = 0; + nonConstSSL->extensions = sslExts; + + nonConstSSL->options.tls = 0; + nonConstSSL->options.tls1_1 = 0; + nonConstSSL->options.tls1_3 = 0; + } +dtls13_cleanup: + TLSX_FreeAll(parsedExts, ssl->heap); + } + else + ret = SendAlert((WOLFSSL*)ssl, alert_fatal, illegal_parameter); + return ret; +} +#endif + static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, PskInfo* pskInfo) { @@ -478,230 +712,7 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, (void)pskInfo; #ifdef WOLFSSL_DTLS13 if (isTls13) { -#ifdef WOLFSSL_SEND_HRR_COOKIE - if (ch->cookie.size == 0) { - TLSX* parsedExts = NULL; - WolfSSL_ConstVector tlsx; - Suites suites; - word16 len; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - byte haveKS = 0; - byte usePSK = 0; - byte doKE = 0; -#endif - CipherSuite cs; - CipherSpecs specs; - - XMEMSET(&cs, 0, sizeof(cs)); - XMEMSET(&specs, 0, sizeof(specs)); - - /* We need to echo the session ID sent by the client */ - if (ch->sessionId.size > ID_LEN) { - /* Too large. We can't echo this. */ - ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); - } - - /* Hashes are reset in SendTls13ServerHello when sending a HRR */ - ret = Dtls13HashHandshakeType((WOLFSSL*)ssl, ch->raw, ch->length, - client_hello); - if (ret != 0) - goto dtls13_cleanup; - - /* Populate the suites struct to find a common ciphersuite */ - XMEMSET(&suites, 0, sizeof(suites)); - suites.suiteSz = (word16)ch->cipherSuite.size; - if ((suites.suiteSz % 2) != 0) - ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); - if (suites.suiteSz > WOLFSSL_MAX_SUITE_SZ) - ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - XMEMCPY(suites.suites, ch->cipherSuite.elements, suites.suiteSz); - - /* Populate extensions */ - - /* Supported versions always need to be present. Has to appear after - * key share as that is the order we reconstruct it in - * RestartHandshakeHashWithCookie. */ - ret = TLSX_Push(&parsedExts, - TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); - if (ret != 0) - goto dtls13_cleanup; - /* Set that this is a response extension */ - parsedExts->resp = 1; - - ret = CopyExtensions(ssl->extensions, &parsedExts, ssl->heap); - if (ret != 0) - goto dtls13_cleanup; - - /* Signature algs */ - ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size > OPAQUE16_LEN) { - ato16(tlsx.elements, &len); - if (len != tlsx.size - OPAQUE16_LEN) - ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - if ((len % 2) != 0) - ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - suites.hashSigAlgoSz = len; - XMEMCPY(suites.hashSigAlgo, tlsx.elements + OPAQUE16_LEN, - len); - } - - /* Supported groups */ - ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size != 0) { - ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, - (word16)tlsx.size, 1, &parsedExts); - if (ret != 0) - goto dtls13_cleanup; - } - - /* Key share */ - ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size != 0) { - ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, - (word16)tlsx.size, &parsedExts); - if (ret != 0) - goto dtls13_cleanup; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - haveKS = 1; -#endif - } - -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - /* Pre-shared key */ - ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size != 0) { - /* Let's just assume that the binders are correct here. We will - * actually verify this in the stateful part of the processing - * and if they don't match we will error out there anyway. */ - byte modes; - -#ifndef NO_PSK - /* When we didn't find a valid ticket ask the user for the - * ciphersuite matching this identity */ - if (!pskInfo->isValid) { - if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, - tlsx.elements, tlsx.size, ssl->heap) == 0) - FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites); - /* Revert to full handshake if PSK parsing failed */ - } -#endif - - if (pskInfo->isValid) { - ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size == 0) - ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); - ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, - client_hello, &modes); - if (ret != 0) - goto dtls13_cleanup; - if ((modes & (1 << PSK_DHE_KE)) && - !ssl->options.noPskDheKe) { - if (!haveKS) - ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); - doKE = 1; - } - else if ((modes & (1 << PSK_KE)) == 0) { - ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); - } - usePSK = 1; - } - } -#endif - -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (usePSK && pskInfo->isValid) { - cs.cipherSuite0 = pskInfo->cipherSuite0; - cs.cipherSuite = pskInfo->cipherSuite; - - if (doKE) { - byte searched = 0; - ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE, - &searched); - if (ret != 0) - goto dtls13_cleanup; - if (cs.clientKSE == NULL && searched) - cs.doHelloRetry = 1; - } - } - else -#endif - { - ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); - if (ret < 0) { - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); - SendAlert((WOLFSSL*)ssl, alert_fatal, handshake_failure); - goto dtls13_cleanup; - } - } - if (cs.doHelloRetry) { - ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts); - if (ret != 0) - goto dtls13_cleanup; - } - else { - /* Need to remove the keyshare ext if we found a common group - * and are not doing curve negotiation. */ - TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); - } - - { - WOLFSSL* nonConstSSL = (WOLFSSL*)ssl; - TLSX* sslExts = nonConstSSL->extensions; - - /* This is required to correctly generate the hash */ - ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, - cs.cipherSuite, &nonConstSSL->specs, NULL); - if (ret != 0) - goto dtls13_cleanup; - nonConstSSL->options.tls = 1; - nonConstSSL->options.tls1_1 = 1; - nonConstSSL->options.tls1_3 = 1; - - XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, - ch->sessionId.size); - nonConstSSL->session->sessionIDSz = (byte)ch->sessionId.size; - nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; - nonConstSSL->options.cipherSuite = cs.cipherSuite; - nonConstSSL->extensions = parsedExts; - - ret = SendTls13ServerHello(nonConstSSL, hello_retry_request); - - /* Can be modified inside SendTls13ServerHello */ - parsedExts = nonConstSSL->extensions; - - InitCipherSpecs(&nonConstSSL->specs); - - nonConstSSL->session->sessionIDSz = 0; - nonConstSSL->options.cipherSuite0 = 0; - nonConstSSL->options.cipherSuite = 0; - nonConstSSL->extensions = sslExts; - - nonConstSSL->options.tls = 0; - nonConstSSL->options.tls1_1 = 0; - nonConstSSL->options.tls1_3 = 0; - } -dtls13_cleanup: - TLSX_FreeAll(parsedExts, ssl->heap); - } - else - ret = SendAlert((WOLFSSL*)ssl, alert_fatal, illegal_parameter); -#else -#error "WOLFSSL_SEND_HRR_COOKIE has to be defined to use DTLS 1.3 server" -#endif + ret = SendStatelessReplyDtls13(ssl, ch, pskInfo); } else #endif From 57dccc4cf4685f262e6e144e90d0976af42c6feb Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 24 Jan 2023 20:24:50 +0100 Subject: [PATCH 08/29] Calculate cookie in SendStatelessReplyDtls13() Not touching ssl->hsHashes while in stateless mode --- src/dtls.c | 32 +++++++++++------- src/dtls13.c | 30 ++++++++++++----- src/tls.c | 17 +++++++--- src/tls13.c | 84 ++++++++++++++++++++++++++-------------------- wolfssl/internal.h | 10 ++++-- 5 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index b5f24f953..dac622c69 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -492,9 +492,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, #endif CipherSuite cs; CipherSpecs specs; + byte cookieHash[WC_MAX_DIGEST_SIZE]; + int cookieHashSz; XMEMSET(&cs, 0, sizeof(cs)); - XMEMSET(&specs, 0, sizeof(specs)); /* We need to echo the session ID sent by the client */ if (ch->sessionId.size > ID_LEN) { @@ -502,12 +503,6 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); } - /* Hashes are reset in SendTls13ServerHello when sending a HRR */ - ret = Dtls13HashHandshakeType((WOLFSSL*)ssl, ch->raw, ch->length, - client_hello); - if (ret != 0) - goto dtls13_cleanup; - /* Populate the suites struct to find a common ciphersuite */ XMEMSET(&suites, 0, sizeof(suites)); suites.suiteSz = (word16)ch->cipherSuite.size; @@ -659,13 +654,28 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); } + /* This is required to correctly generate the hash */ + ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, + cs.cipherSuite, &specs, NULL); + if (ret != 0) + goto dtls13_cleanup; + + /* Calculate the cookie hash */ + ret = Dtls13HashClientHello(ssl, cookieHash, &cookieHashSz, ch->raw, + ch->length, &specs); + if (ret != 0) + goto dtls13_cleanup; + + /* Push the cookie to extensions */ + ret = CreateCookieExt(ssl, cookieHash, cookieHashSz, &parsedExts, + cs.cipherSuite0, cs.cipherSuite); + if (ret != 0) + goto dtls13_cleanup; + { WOLFSSL* nonConstSSL = (WOLFSSL*)ssl; TLSX* sslExts = nonConstSSL->extensions; - /* This is required to correctly generate the hash */ - ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, - cs.cipherSuite, &nonConstSSL->specs, NULL); if (ret != 0) goto dtls13_cleanup; nonConstSSL->options.tls = 1; @@ -684,8 +694,6 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, /* Can be modified inside SendTls13ServerHello */ parsedExts = nonConstSSL->extensions; - InitCipherSpecs(&nonConstSSL->specs); - nonConstSSL->session->sessionIDSz = 0; nonConstSSL->options.cipherSuite0 = 0; nonConstSSL->options.cipherSuite = 0; diff --git a/src/dtls13.c b/src/dtls13.c index 91bddcf8f..4a1cced90 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -437,24 +437,36 @@ static int Dtls13SendNow(WOLFSSL* ssl, enum HandShakeType handshakeType) /* Handshake header DTLS only fields are not inlcuded in the transcript hash. * body points to the body of the DTLSHandshake message. */ -int Dtls13HashHandshakeType(WOLFSSL* ssl, const byte* body, word32 length, - enum HandShakeType handshakeType) +int Dtls13HashClientHello(const WOLFSSL* ssl, byte* hash, int* hashSz, + const byte* body, word32 length, CipherSpecs* specs) { /* msg_type(1) + length (3) */ byte header[OPAQUE32_LEN]; int ret; + wc_HashAlg hashCtx; + int type = wolfSSL_GetHmacType_ex(specs); - header[0] = (byte)handshakeType; + header[0] = (byte)client_hello; c32to24(length, header + 1); - ret = HashRaw(ssl, header, OPAQUE32_LEN); - if (ret != 0) - return ret; - - return HashRaw(ssl, body, length); + ret = wc_HashInit_ex(&hashCtx, type, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_HashUpdate(&hashCtx, type, header, OPAQUE32_LEN); + if (ret == 0) + ret = wc_HashUpdate(&hashCtx, type, body, length); + if (ret == 0) + ret = wc_HashFinal(&hashCtx, type, hash); + if (ret == 0) { + *hashSz = wc_HashGetDigestSize(type); + if (*hashSz < 0) + ret = *hashSz; + } + wc_HashFree(&hashCtx, type); + } + return ret; } -/* Handshake header DTLS only fields are not inlcuded in the transcript hash */ +/* Handshake header DTLS only fields are not included in the transcript hash */ int Dtls13HashHandshake(WOLFSSL* ssl, const byte* input, word16 length) { int ret; diff --git a/src/tls.c b/src/tls.c index 46027e7f7..399890938 100644 --- a/src/tls.c +++ b/src/tls.c @@ -663,14 +663,12 @@ int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len, return ret; } - -/* return HMAC digest type in wolfSSL format */ -int wolfSSL_GetHmacType(WOLFSSL* ssl) +int wolfSSL_GetHmacType_ex(CipherSpecs* specs) { - if (ssl == NULL) + if (specs == NULL) return BAD_FUNC_ARG; - switch (ssl->specs.mac_algorithm) { + switch (specs->mac_algorithm) { #ifndef NO_MD5 case md5_mac: { @@ -709,6 +707,15 @@ int wolfSSL_GetHmacType(WOLFSSL* ssl) } } +/* return HMAC digest type in wolfSSL format */ +int wolfSSL_GetHmacType(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_GetHmacType_ex(&ssl->specs); +} + int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, int verify) diff --git a/src/tls13.c b/src/tls13.c index fcce88f52..d08951a82 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3337,14 +3337,34 @@ byte SuiteMac(const byte* suite) * hashSz The size of the hash data in bytes. * returns 0 on success, otherwise failure. */ -static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, - TLSX** exts) +int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, + TLSX** exts, byte cipherSuite0, byte cipherSuite) { int ret; byte mac[WC_MAX_DIGEST_SIZE] = {0}; Hmac cookieHmac; byte cookieType = 0; byte macSz = 0; + byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; + TLSX* ext; + word16 cookieSz = 0; + + /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ + cookie[cookieSz++] = hashSz; + XMEMCPY(cookie + cookieSz, hash, hashSz); + cookieSz += hashSz; + cookie[cookieSz++] = cipherSuite0; + cookie[cookieSz++] = cipherSuite; + if ((ext = TLSX_Find(*exts, TLSX_KEY_SHARE)) != NULL) { + KeyShareEntry* kse = (KeyShareEntry*)ext->data; + if (kse == NULL) { + WOLFSSL_MSG("KeyShareEntry can't be empty when negotiating " + "parameters"); + return BAD_STATE_E; + } + c16toa(kse->group, cookie + cookieSz); + cookieSz += OPAQUE16_LEN; + } #if !defined(NO_SHA) && defined(NO_SHA256) cookieType = SHA; @@ -3362,7 +3382,7 @@ static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, ssl->buffers.tls13CookieSecret.length); } if (ret == 0) - ret = wc_HmacUpdate(&cookieHmac, hash, hashSz); + ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz); #ifdef WOLFSSL_DTLS13 /* Tie cookie to peer address */ if (ret == 0) { @@ -3381,7 +3401,7 @@ static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, return ret; /* The cookie data is the hash and the integrity check. */ - return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1, exts); + return TLSX_Cookie_Use(ssl, cookie, cookieSz, mac, macSz, 1, exts); } #endif @@ -3391,16 +3411,13 @@ static int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, #define HRR_MAX_HS_HEADER_SZ HANDSHAKE_HEADER_SZ #endif /* WOLFSSL_DTLS13 */ -static int CreateCookieHash(const WOLFSSL* ssl, byte** hash, byte* hashSz, +static int CreateCookie(const WOLFSSL* ssl, byte** hash, byte* hashSz, Hashes* hashes, TLSX** exts) { - int ret; + int ret = 0; (void)exts; - ret = BuildCertHashes(ssl, hashes); - if (ret != 0) - return ret; *hash = NULL; switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 @@ -3426,30 +3443,9 @@ static int CreateCookieHash(const WOLFSSL* ssl, byte** hash, byte* hashSz, return BAD_FUNC_ARG; #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) - if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) { - byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; - TLSX* ext; - word16 idx = 0; - - /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ - cookie[idx++] = *hashSz; - if (*hash) - XMEMCPY(cookie + idx, *hash, *hashSz); - idx += *hashSz; - cookie[idx++] = ssl->options.cipherSuite0; - cookie[idx++] = ssl->options.cipherSuite; - if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) { - KeyShareEntry* kse = (KeyShareEntry*)ext->data; - if (kse == NULL) { - WOLFSSL_MSG("KeyShareEntry can't be empty when negotiating " - "parameters"); - return BAD_STATE_E; - } - c16toa(kse->group, cookie + idx); - idx += OPAQUE16_LEN; - } - ret = CreateCookieExt(ssl, cookie, idx, exts); - } + if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) + ret = CreateCookieExt(ssl, *hash, *hashSz, exts, + ssl->options.cipherSuite0, ssl->options.cipherSuite); #endif return ret; } @@ -3467,7 +3463,10 @@ int RestartHandshakeHash(WOLFSSL* ssl) byte* hash = NULL; byte hashSz = 0; - ret = CreateCookieHash(ssl, &hash, &hashSz, &hashes, &ssl->extensions); + ret = BuildCertHashes(ssl, &hashes); + if (ret != 0) + return ret; + ret = CreateCookie(ssl, &hash, &hashSz, &hashes, &ssl->extensions); if (ret != 0) return ret; #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) @@ -6883,7 +6882,13 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND); WOLFSSL_ENTER("SendTls13ServerHello"); - if (extMsgType == hello_retry_request) { + /* When ssl->options.dtlsStateful is not set then cookie is calculated in + * dtls.c */ + if (extMsgType == hello_retry_request +#ifdef WOLFSSL_DTLS13 + && (!ssl->options.dtls || ssl->options.dtlsStateful) +#endif + ) { WOLFSSL_MSG("wolfSSL Sending HelloRetryRequest"); if ((ret = RestartHandshakeHash(ssl)) < 0) return ret; @@ -6970,7 +6975,14 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) if (ssl->options.sendCookie && extMsgType == hello_retry_request) { /* Reset the hashes from here. We will be able to restart the hashes * from the cookie in RestartHandshakeHashWithCookie */ - ret = InitHandshakeHashes(ssl); +#ifdef WOLFSSL_DTLS13 + /* When ssl->options.dtlsStateful is not set then cookie is calculated + * in dtls.c */ + if (ssl->options.dtls && !ssl->options.dtlsStateful) + ret = 0; + else +#endif + ret = InitHandshakeHashes(ssl); } else #endif diff --git a/wolfssl/internal.h b/wolfssl/internal.h index add0d2c6f..9a6898911 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -5863,6 +5863,10 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); WOLFSSL_LOCAL int SendHelloVerifyRequest(WOLFSSL* ssl, const byte* cookie, byte cookieSz); + WOLFSSL_LOCAL int CreateCookieExt(const WOLFSSL* ssl, byte* hash, + word16 hashSz, TLSX** exts, + byte cipherSuite0, byte cipherSuite); + #if !defined(NO_WOLFSSL_SERVER) WOLFSSL_LOCAL int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz); @@ -6128,8 +6132,8 @@ WOLFSSL_LOCAL int Dtls13RtxProcessingCertificate(WOLFSSL* ssl, byte* input, word32 inputSize); WOLFSSL_LOCAL int Dtls13HashHandshake(WOLFSSL* ssl, const byte* input, word16 length); -WOLFSSL_LOCAL int Dtls13HashHandshakeType(WOLFSSL* ssl, const byte* body, - word32 length, enum HandShakeType handshakeType); +WOLFSSL_LOCAL int Dtls13HashClientHello(const WOLFSSL* ssl, byte* hash, + int* hashSz, const byte* body, word32 length, CipherSpecs* specs); WOLFSSL_LOCAL void Dtls13FreeFsmResources(WOLFSSL* ssl); WOLFSSL_LOCAL int Dtls13RtxTimeout(WOLFSSL* ssl); WOLFSSL_LOCAL int Dtls13ProcessBufferedMessages(WOLFSSL* ssl); @@ -6218,6 +6222,8 @@ WOLFSSL_LOCAL int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* foundSuite); #endif +WOLFSSL_LOCAL int wolfSSL_GetHmacType_ex(CipherSpecs* specs); + #ifdef __cplusplus } /* extern "C" */ #endif From 969c610ef7cd6ea4106de270fc57279e9ab43282 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 26 Jan 2023 19:54:30 +0100 Subject: [PATCH 09/29] Fix unused variable --- src/dtls.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dtls.c b/src/dtls.c index dac622c69..3b5e825f4 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -480,6 +480,9 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, PskInfo* pskInfo) { int ret = -1; + + (void)pskInfo; + if (ch->cookie.size == 0) { TLSX* parsedExts = NULL; WolfSSL_ConstVector tlsx; From 0264df154663f35a0ce11771adcf4d8c13966961 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 31 Jan 2023 11:55:56 +0100 Subject: [PATCH 10/29] Definition was defined out in some configs --- wolfssl/internal.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9a6898911..4a2108a51 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -5863,10 +5863,6 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); WOLFSSL_LOCAL int SendHelloVerifyRequest(WOLFSSL* ssl, const byte* cookie, byte cookieSz); - WOLFSSL_LOCAL int CreateCookieExt(const WOLFSSL* ssl, byte* hash, - word16 hashSz, TLSX** exts, - byte cipherSuite0, byte cipherSuite); - #if !defined(NO_WOLFSSL_SERVER) WOLFSSL_LOCAL int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz); @@ -6224,6 +6220,12 @@ WOLFSSL_LOCAL int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, WOLFSSL_LOCAL int wolfSSL_GetHmacType_ex(CipherSpecs* specs); +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) +WOLFSSL_LOCAL int CreateCookieExt(const WOLFSSL* ssl, byte* hash, + word16 hashSz, TLSX** exts, + byte cipherSuite0, byte cipherSuite); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif From b5e7761e585ce8c849fd18882610fd002826c787 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 31 Jan 2023 13:47:46 +0100 Subject: [PATCH 11/29] For DTLS 1.3 use PSK for ticket Resumption info is also necessary when WOLFSSL_DTLS_NO_HVR_ON_RESUME is not defined. --- src/dtls.c | 66 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 3b5e825f4..9196cea08 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -273,17 +273,24 @@ static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, } #endif -#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME +#if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) #ifdef HAVE_SESSION_TICKET static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, - PskInfo* pskInfo) + PskInfo* pskInfo, byte isTls13) { WolfSSL_ConstVector tlsxSessionTicket; byte tempTicket[SESSION_TICKET_LEN]; InternalTicket* it; int ret; - ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts); + (void)isTls13; + +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) + if (isTls13) + ret = TlsxFindByType(&tlsxSessionTicket, TLSX_PRE_SHARED_KEY, exts); + else +#endif + ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts); if (ret != 0) return ret; if (tlsxSessionTicket.size == 0) @@ -363,12 +370,13 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID } static int TlsResumptionIsValid(const WOLFSSL* ssl, WolfSSL_CH* ch, - PskInfo* pskInfo) + PskInfo* pskInfo, byte isTls13) { int ret; + (void)isTls13; #ifdef HAVE_SESSION_TICKET - ret = TlsTicketIsValid(ssl, ch->extension, pskInfo); + ret = TlsTicketIsValid(ssl, ch->extension, pskInfo, isTls13); if (ret != 0) return ret; if (pskInfo->isValid) @@ -377,18 +385,16 @@ static int TlsResumptionIsValid(const WOLFSSL* ssl, WolfSSL_CH* ch, ret = TlsSessionIdIsValid(ssl, ch->sessionId, pskInfo); return ret; } -#endif /* WOLFSSL_DTLS_NO_HVR_ON_RESUME */ +#endif /* WOLFSSL_DTLS13 || WOLFSSL_DTLS_NO_HVR_ON_RESUME */ #ifdef WOLFSSL_DTLS13 static int TlsCheckSupportedVersion(const WOLFSSL* ssl, - WolfSSL_CH* ch, byte *isTls13, PskInfo* pskInfo) + WolfSSL_CH* ch, byte *isTls13) { WolfSSL_ConstVector tlsxSupportedVersions; int ret; ProtocolVersion pv = ssl->version; - (void)pskInfo; - ret = TlsxFindByType(&tlsxSupportedVersions, TLSX_SUPPORTED_VERSIONS, ch->extension); if (ret != 0) @@ -401,11 +407,6 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, (word16)tlsxSupportedVersions.size, client_hello, &pv, NULL, NULL); if (ret != 0) return ret; -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - if (pskInfo->isValid && (pskInfo->pv.major != pv.major || - pskInfo->pv.minor != pv.minor)) - return VERSION_ERROR; -#endif if (IsAtLeastTLSv1_3(pv)) *isTls13 = 1; else @@ -756,19 +757,9 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, if (ret != 0) return ret; -#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME - ret = TlsResumptionIsValid(ssl, &ch, &pskInfo); - if (ret != 0) - return ret; - if (pskInfo.isValid) { - ssl->options.dtlsStateful = 1; - return 0; - } -#endif /* WOLFSSL_DTLS_NO_HVR_ON_RESUME */ - #ifdef WOLFSSL_DTLS13 if (IsAtLeastTLSv1_3(ssl->version)) { - ret = TlsCheckSupportedVersion(ssl, &ch, &isTls13, &pskInfo); + ret = TlsCheckSupportedVersion(ssl, &ch, &isTls13); if (ret != 0) return ret; if (isTls13) { @@ -779,6 +770,31 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, } #endif +#if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) + ret = TlsResumptionIsValid(ssl, &ch, &pskInfo, isTls13); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME + if (pskInfo.isValid) { + ssl->options.dtlsStateful = 1; + return 0; + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (pskInfo.isValid) { + if (IsAtLeastTLSv1_3(pskInfo.pv)) { + if (!isTls13) + return VERSION_ERROR; + } + else { + if (isTls13) + return VERSION_ERROR; + } + } +#endif + if (ch.cookie.size == 0) { ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); } From 5b0903a82d33274a2b066a6bc3dddeb0a6404c1e Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 31 Jan 2023 14:42:26 +0100 Subject: [PATCH 12/29] Missing casts --- src/dtls.c | 4 ++-- src/tls13.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 9196cea08..381372032 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -671,8 +671,8 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, goto dtls13_cleanup; /* Push the cookie to extensions */ - ret = CreateCookieExt(ssl, cookieHash, cookieHashSz, &parsedExts, - cs.cipherSuite0, cs.cipherSuite); + ret = CreateCookieExt(ssl, cookieHash, (word16)cookieHashSz, + &parsedExts, cs.cipherSuite0, cs.cipherSuite); if (ret != 0) goto dtls13_cleanup; diff --git a/src/tls13.c b/src/tls13.c index d08951a82..96e6137b9 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3350,7 +3350,7 @@ int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz, word16 cookieSz = 0; /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ - cookie[cookieSz++] = hashSz; + cookie[cookieSz++] = (byte)hashSz; XMEMCPY(cookie + cookieSz, hash, hashSz); cookieSz += hashSz; cookie[cookieSz++] = cipherSuite0; From 51a384eba578cf37d9d55d719357d3e014653ef5 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 7 Feb 2023 17:16:33 +0100 Subject: [PATCH 13/29] Read cookie extension into separate field --- src/dtls.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 381372032..1f184d0b2 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -111,6 +111,7 @@ typedef struct WolfSSL_CH { WolfSSL_ConstVector cipherSuite; WolfSSL_ConstVector compression; WolfSSL_ConstVector extension; + WolfSSL_ConstVector cookieExt; const byte* raw; word32 length; /* Store the DTLS 1.2 cookie since we can just compute it once in dtls.c */ @@ -184,13 +185,13 @@ static int CheckDtlsCookie(const WOLFSSL* ssl, WolfSSL_CH* ch, #ifdef WOLFSSL_DTLS13 if (isTls13) { word16 len; - if (ch->cookie.size < OPAQUE16_LEN + 1) + if (ch->cookieExt.size < OPAQUE16_LEN + 1) return BUFFER_E; - ato16(ch->cookie.elements, &len); - if (ch->cookie.size - OPAQUE16_LEN != len) + ato16(ch->cookieExt.elements, &len); + if (ch->cookieExt.size - OPAQUE16_LEN != len) return BUFFER_E; - ret = TlsCheckCookie(ssl, ch->cookie.elements + OPAQUE16_LEN, - (word16)(ch->cookie.size - OPAQUE16_LEN)); + ret = TlsCheckCookie(ssl, ch->cookieExt.elements + OPAQUE16_LEN, + (word16)(ch->cookieExt.size - OPAQUE16_LEN)); if (ret < 0 && ret != HRR_COOKIE_ERROR) return ret; *cookieGood = ret > 0; @@ -484,7 +485,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, (void)pskInfo; - if (ch->cookie.size == 0) { + if (ch->cookieExt.size == 0) { TLSX* parsedExts = NULL; WolfSSL_ConstVector tlsx; Suites suites; @@ -763,7 +764,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, if (ret != 0) return ret; if (isTls13) { - ret = TlsxFindByType(&ch.cookie, TLSX_COOKIE, ch.extension); + ret = TlsxFindByType(&ch.cookieExt, TLSX_COOKIE, ch.extension); if (ret != 0) return ret; } @@ -795,7 +796,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, } #endif - if (ch.cookie.size == 0) { + if (ch.cookie.size == 0 && ch.cookieExt.size == 0) { ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); } else { From 5f657524147f3e0d1bd2f39d1f89dff78ebab40d Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 8 Feb 2023 14:02:52 +0100 Subject: [PATCH 14/29] Refactor alerts into one location Remove previous stateless code. Now all DTLS 1.3 stateless handling is done in dtls.c --- src/dtls.c | 456 ++++++++++++++++++++---------------- src/dtls13.c | 2 +- src/internal.c | 44 +++- src/tls13.c | 157 ++++--------- wolfssl/internal.h | 3 + wolfssl/ssl.h | 1 + wolfssl/wolfcrypt/logging.h | 2 +- 7 files changed, 335 insertions(+), 330 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 1f184d0b2..986869749 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -82,6 +82,23 @@ void DtlsResetState(WOLFSSL* ssl) ssl->options.tls1_3 = 0; } +int DtlsIgnoreError(int err) +{ + /* Whitelist of errors not to ignore */ + switch (err) { + case MEMORY_E: + case MEMORY_ERROR: + case ASYNC_INIT_E: + case ASYNC_OP_E: + case SOCKET_ERROR_E: + case WANT_READ: + case WANT_WRITE: + return 0; + default: + return 1; + } +} + #if !defined(NO_WOLFSSL_SERVER) #if defined(NO_SHA) && defined(NO_SHA256) @@ -482,237 +499,235 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, PskInfo* pskInfo) { int ret = -1; + TLSX* parsedExts = NULL; + WolfSSL_ConstVector tlsx; + Suites suites; + word16 len; + byte haveSA = 0; + byte haveKS = 0; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + byte usePSK = 0; + byte doKE = 0; +#endif + CipherSuite cs; + CipherSpecs specs; + byte cookieHash[WC_MAX_DIGEST_SIZE]; + int cookieHashSz; (void)pskInfo; - if (ch->cookieExt.size == 0) { - TLSX* parsedExts = NULL; - WolfSSL_ConstVector tlsx; - Suites suites; - word16 len; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - byte haveKS = 0; - byte usePSK = 0; - byte doKE = 0; -#endif - CipherSuite cs; - CipherSpecs specs; - byte cookieHash[WC_MAX_DIGEST_SIZE]; - int cookieHashSz; + XMEMSET(&cs, 0, sizeof(cs)); - XMEMSET(&cs, 0, sizeof(cs)); + /* We need to echo the session ID sent by the client */ + if (ch->sessionId.size > ID_LEN) { + /* Too large. We can't echo this. */ + ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); + } - /* We need to echo the session ID sent by the client */ - if (ch->sessionId.size > ID_LEN) { - /* Too large. We can't echo this. */ - ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); - } + /* Populate the suites struct to find a common ciphersuite */ + XMEMSET(&suites, 0, sizeof(suites)); + suites.suiteSz = (word16)ch->cipherSuite.size; + if ((suites.suiteSz % 2) != 0) + ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); + if (suites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + XMEMCPY(suites.suites, ch->cipherSuite.elements, suites.suiteSz); - /* Populate the suites struct to find a common ciphersuite */ - XMEMSET(&suites, 0, sizeof(suites)); - suites.suiteSz = (word16)ch->cipherSuite.size; - if ((suites.suiteSz % 2) != 0) - ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); - if (suites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + /* Populate extensions */ + + /* Supported versions always need to be present. Has to appear after + * key share as that is the order we reconstruct it in + * RestartHandshakeHashWithCookie. */ + ret = TLSX_Push(&parsedExts, + TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); + if (ret != 0) + goto dtls13_cleanup; + /* Set that this is a response extension */ + parsedExts->resp = 1; + + ret = CopyExtensions(ssl->extensions, &parsedExts, ssl->heap); + if (ret != 0) + goto dtls13_cleanup; + + /* Signature algs */ + ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size > OPAQUE16_LEN) { + ato16(tlsx.elements, &len); + if (len != tlsx.size - OPAQUE16_LEN) ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - XMEMCPY(suites.suites, ch->cipherSuite.elements, suites.suiteSz); + if ((len % 2) != 0) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); + suites.hashSigAlgoSz = len; + XMEMCPY(suites.hashSigAlgo, tlsx.elements + OPAQUE16_LEN, + len); + haveSA = 1; + } - /* Populate extensions */ - - /* Supported versions always need to be present. Has to appear after - * key share as that is the order we reconstruct it in - * RestartHandshakeHashWithCookie. */ - ret = TLSX_Push(&parsedExts, - TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap); + /* Supported groups */ + ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, + (word16)tlsx.size, 1, &parsedExts); if (ret != 0) goto dtls13_cleanup; - /* Set that this is a response extension */ - parsedExts->resp = 1; + } - ret = CopyExtensions(ssl->extensions, &parsedExts, ssl->heap); + /* Key share */ + ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, + (word16)tlsx.size, &parsedExts); if (ret != 0) goto dtls13_cleanup; - - /* Signature algs */ - ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size > OPAQUE16_LEN) { - ato16(tlsx.elements, &len); - if (len != tlsx.size - OPAQUE16_LEN) - ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - if ((len % 2) != 0) - ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - suites.hashSigAlgoSz = len; - XMEMCPY(suites.hashSigAlgo, tlsx.elements + OPAQUE16_LEN, - len); - } - - /* Supported groups */ - ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size != 0) { - ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, - (word16)tlsx.size, 1, &parsedExts); - if (ret != 0) - goto dtls13_cleanup; - } - - /* Key share */ - ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size != 0) { - ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, - (word16)tlsx.size, &parsedExts); - if (ret != 0) - goto dtls13_cleanup; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - haveKS = 1; -#endif - } + haveKS = 1; + } #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - /* Pre-shared key */ - ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size != 0) { - /* Let's just assume that the binders are correct here. We will - * actually verify this in the stateful part of the processing - * and if they don't match we will error out there anyway. */ - byte modes; + /* Pre-shared key */ + ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size != 0) { + /* Let's just assume that the binders are correct here. We will + * actually verify this in the stateful part of the processing + * and if they don't match we will error out there anyway. */ + byte modes; #ifndef NO_PSK - /* When we didn't find a valid ticket ask the user for the - * ciphersuite matching this identity */ - if (!pskInfo->isValid) { - if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, - tlsx.elements, tlsx.size, ssl->heap) == 0) - FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites); - /* Revert to full handshake if PSK parsing failed */ - } + /* When we didn't find a valid ticket ask the user for the + * ciphersuite matching this identity */ + if (!pskInfo->isValid) { + if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, + tlsx.elements, tlsx.size, ssl->heap) == 0) + FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites); + /* Revert to full handshake if PSK parsing failed */ + } #endif - if (pskInfo->isValid) { - ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, - ch->extension); - if (ret != 0) - goto dtls13_cleanup; - if (tlsx.size == 0) - ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); - ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, - client_hello, &modes); - if (ret != 0) - goto dtls13_cleanup; - if ((modes & (1 << PSK_DHE_KE)) && - !ssl->options.noPskDheKe) { - if (!haveKS) - ERROR_OUT(MISSING_HANDSHAKE_DATA, dtls13_cleanup); - doKE = 1; - } - else if ((modes & (1 << PSK_KE)) == 0) { - ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); - } - usePSK = 1; + if (pskInfo->isValid) { + ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, + ch->extension); + if (ret != 0) + goto dtls13_cleanup; + if (tlsx.size == 0) + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, + client_hello, &modes); + if (ret != 0) + goto dtls13_cleanup; + if ((modes & (1 << PSK_DHE_KE)) && + !ssl->options.noPskDheKe) { + if (!haveKS) + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + doKE = 1; } + else if ((modes & (1 << PSK_KE)) == 0) { + ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); + } + usePSK = 1; } + } #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (usePSK && pskInfo->isValid) { - cs.cipherSuite0 = pskInfo->cipherSuite0; - cs.cipherSuite = pskInfo->cipherSuite; + if (usePSK && pskInfo->isValid) { + cs.cipherSuite0 = pskInfo->cipherSuite0; + cs.cipherSuite = pskInfo->cipherSuite; - if (doKE) { - byte searched = 0; - ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE, - &searched); - if (ret != 0) - goto dtls13_cleanup; - if (cs.clientKSE == NULL && searched) - cs.doHelloRetry = 1; - } - } - else -#endif - { - ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); - if (ret < 0) { - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); - SendAlert((WOLFSSL*)ssl, alert_fatal, handshake_failure); - goto dtls13_cleanup; - } - } - if (cs.doHelloRetry) { - ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts); + if (doKE) { + byte searched = 0; + ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE, + &searched); if (ret != 0) goto dtls13_cleanup; + if (cs.clientKSE == NULL && searched) + cs.doHelloRetry = 1; } - else { - /* Need to remove the keyshare ext if we found a common group - * and are not doing curve negotiation. */ - TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); - } - - /* This is required to correctly generate the hash */ - ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, - cs.cipherSuite, &specs, NULL); - if (ret != 0) - goto dtls13_cleanup; - - /* Calculate the cookie hash */ - ret = Dtls13HashClientHello(ssl, cookieHash, &cookieHashSz, ch->raw, - ch->length, &specs); - if (ret != 0) - goto dtls13_cleanup; - - /* Push the cookie to extensions */ - ret = CreateCookieExt(ssl, cookieHash, (word16)cookieHashSz, - &parsedExts, cs.cipherSuite0, cs.cipherSuite); - if (ret != 0) - goto dtls13_cleanup; - - { - WOLFSSL* nonConstSSL = (WOLFSSL*)ssl; - TLSX* sslExts = nonConstSSL->extensions; - - if (ret != 0) - goto dtls13_cleanup; - nonConstSSL->options.tls = 1; - nonConstSSL->options.tls1_1 = 1; - nonConstSSL->options.tls1_3 = 1; - - XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, - ch->sessionId.size); - nonConstSSL->session->sessionIDSz = (byte)ch->sessionId.size; - nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; - nonConstSSL->options.cipherSuite = cs.cipherSuite; - nonConstSSL->extensions = parsedExts; - - ret = SendTls13ServerHello(nonConstSSL, hello_retry_request); - - /* Can be modified inside SendTls13ServerHello */ - parsedExts = nonConstSSL->extensions; - - nonConstSSL->session->sessionIDSz = 0; - nonConstSSL->options.cipherSuite0 = 0; - nonConstSSL->options.cipherSuite = 0; - nonConstSSL->extensions = sslExts; - - nonConstSSL->options.tls = 0; - nonConstSSL->options.tls1_1 = 0; - nonConstSSL->options.tls1_3 = 0; - } -dtls13_cleanup: - TLSX_FreeAll(parsedExts, ssl->heap); } else - ret = SendAlert((WOLFSSL*)ssl, alert_fatal, illegal_parameter); +#endif + { + if (!haveKS || !haveSA) { + WOLFSSL_MSG("Client didn't send KeyShare or SigAlgs"); + ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); + } + ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); + if (ret < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); + } + } + if (cs.doHelloRetry) { + ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts); + if (ret != 0) + goto dtls13_cleanup; + } + else { + /* Need to remove the keyshare ext if we found a common group + * and are not doing curve negotiation. */ + TLSX_Remove(&parsedExts, TLSX_KEY_SHARE, ssl->heap); + } + + /* This is required to correctly generate the hash */ + ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, + cs.cipherSuite, &specs, NULL); + if (ret != 0) + goto dtls13_cleanup; + + /* Calculate the cookie hash */ + ret = Dtls13HashClientHello(ssl, cookieHash, &cookieHashSz, ch->raw, + ch->length, &specs); + if (ret != 0) + goto dtls13_cleanup; + + /* Push the cookie to extensions */ + ret = CreateCookieExt(ssl, cookieHash, (word16)cookieHashSz, + &parsedExts, cs.cipherSuite0, cs.cipherSuite); + if (ret != 0) + goto dtls13_cleanup; + + { + WOLFSSL* nonConstSSL = (WOLFSSL*)ssl; + TLSX* sslExts = nonConstSSL->extensions; + + if (ret != 0) + goto dtls13_cleanup; + nonConstSSL->options.tls = 1; + nonConstSSL->options.tls1_1 = 1; + nonConstSSL->options.tls1_3 = 1; + + XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, + ch->sessionId.size); + nonConstSSL->session->sessionIDSz = (byte)ch->sessionId.size; + nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; + nonConstSSL->options.cipherSuite = cs.cipherSuite; + nonConstSSL->extensions = parsedExts; + + ret = SendTls13ServerHello(nonConstSSL, hello_retry_request); + + /* Can be modified inside SendTls13ServerHello */ + parsedExts = nonConstSSL->extensions; + + nonConstSSL->session->sessionIDSz = 0; + nonConstSSL->options.cipherSuite0 = 0; + nonConstSSL->options.cipherSuite = 0; + nonConstSSL->extensions = sslExts; + + nonConstSSL->options.tls = 0; + nonConstSSL->options.tls1_1 = 0; + nonConstSSL->options.tls1_3 = 0; + } +dtls13_cleanup: + TLSX_FreeAll(parsedExts, ssl->heap); return ret; } #endif @@ -742,6 +757,27 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, return ret; } +static int ClientHelloSanityCheck(WolfSSL_CH* ch, byte isTls13) +{ + /* Do basic checks on the basic fields */ + + /* Check the protocol version */ + if (ch->pv->major != DTLS_MAJOR) + return VERSION_ERROR; + if (ch->pv->minor != DTLSv1_2_MINOR && ch->pv->minor != DTLS_MINOR) + return VERSION_ERROR; + if (isTls13) { + if (ch->cookie.size != 0) + return INVALID_PARAMETER; + if (ch->compression.size != COMP_LEN) + return INVALID_PARAMETER; + if (ch->compression.elements[0] != NO_COMPRESSION) + return INVALID_PARAMETER; + } + + return 0; +} + int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { @@ -771,6 +807,10 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, } #endif + ret = ClientHelloSanityCheck(&ch, isTls13); + if (ret != 0) + return ret; + #if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) ret = TlsResumptionIsValid(ssl, &ch, &pskInfo, isTls13); if (ret != 0) @@ -783,7 +823,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, } #endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) +#if defined(WOLFSSL_DTLS13) && defined(HAVE_SESSION_TICKET) if (pskInfo.isValid) { if (IsAtLeastTLSv1_3(pskInfo.pv)) { if (!isTls13) @@ -804,8 +844,16 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, ret = CheckDtlsCookie(ssl, &ch, isTls13, &cookieGood); if (ret != 0) return ret; - if (!cookieGood) - ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); + if (!cookieGood) { +#ifdef WOLFSSL_DTLS13 + /* Invalid cookie for DTLS 1.3 results in an alert. Alert to be sent + * in DoTls13ClientHello. */ + if (isTls13) + ret = INVALID_PARAMETER; + else +#endif + ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); + } else ssl->options.dtlsStateful = 1; } diff --git a/src/dtls13.c b/src/dtls13.c index 4a1cced90..aa0da54b0 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -435,7 +435,7 @@ static int Dtls13SendNow(WOLFSSL* ssl, enum HandShakeType handshakeType) return 0; } -/* Handshake header DTLS only fields are not inlcuded in the transcript hash. +/* Handshake header DTLS only fields are not included in the transcript hash. * body points to the body of the DTLSHandshake message. */ int Dtls13HashClientHello(const WOLFSSL* ssl, byte* hash, int* hashSz, const byte* body, word32 length, CipherSpecs* specs) diff --git a/src/internal.c b/src/internal.c index bf91fd546..9d3d55fe0 100644 --- a/src/internal.c +++ b/src/internal.c @@ -30656,6 +30656,32 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* HAVE_ECC */ + int TranslateErrorToAlert(int err) + { + switch (err) { + case BUFFER_ERROR: + return decode_error; + case EXT_NOT_ALLOWED: + case PEER_KEY_ERROR: + case ECC_PEERKEY_ERROR: + case BAD_KEY_SHARE_DATA: + case PSK_KEY_ERROR: + case INVALID_PARAMETER: + case HRR_COOKIE_ERROR: + return illegal_parameter; + break; + case INCOMPLETE_DATA: + return missing_extension; + case MATCH_SUITE_ERROR: + case MISSING_HANDSHAKE_DATA: + return handshake_failure; + case VERSION_ERROR: + return wolfssl_alert_protocol_version; + default: + return invalid_alert; + } + } + #ifndef NO_WOLFSSL_SERVER @@ -33158,22 +33184,23 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Update the ssl->options.dtlsStateful setting `if` statement in * wolfSSL_accept when changing this one. */ if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl)) { - if (((ssl->keys.dtls_sequence_number_hi == ssl->keys.curSeq_hi && - ssl->keys.dtls_sequence_number_lo < ssl->keys.curSeq_lo) || - (ssl->keys.dtls_sequence_number_hi < ssl->keys.curSeq_hi))) { - /* We should continue with the same sequence number as the - * Client Hello if available. */ - ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; - ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; - } + /* We should continue with the same sequence number as the + * Client Hello. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; /* We should continue with the same handshake number as the * Client Hello. */ ssl->keys.dtls_handshake_number = ssl->keys.dtls_peer_handshake_number; ret = DoClientHelloStateless(ssl, input, inOutIdx, helloSz); if (ret != 0 || !ssl->options.dtlsStateful) { + int alertType = TranslateErrorToAlert(ret); + if (alertType != invalid_alert) + SendAlert(ssl, alert_fatal, alertType); *inOutIdx += helloSz; DtlsResetState(ssl); + if (DtlsIgnoreError(ret)) + ret = 0; return ret; } } @@ -35440,7 +35467,6 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], } ssl->buffers.outputBuffer.length += sendSz; - DtlsResetState(ssl); return SendBuffered(ssl); } diff --git a/src/tls13.c b/src/tls13.c index 96e6137b9..f5ecf1dd6 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -6398,7 +6398,6 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = DoClientHelloStateless(ssl, input, inOutIdx, helloSz); if (ret != 0 || !ssl->options.dtlsStateful) { *inOutIdx += helloSz; - DtlsResetState(ssl); goto exit_dch; } } @@ -6422,8 +6421,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* this check pass for DTLS Major (0xff) */ if (args->pv.major < SSLv3_MAJOR) { WOLFSSL_MSG("Legacy version field contains unsupported value"); - SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version); - ERROR_OUT(INVALID_PARAMETER, exit_dch); + ERROR_OUT(VERSION_ERROR, exit_dch); } #ifdef WOLFSSL_DTLS13 @@ -6501,13 +6499,13 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif sessIdSz = input[args->idx++]; - if (sessIdSz != ID_LEN && sessIdSz != 0) + if (sessIdSz != ID_LEN && sessIdSz != 0) { ERROR_OUT(INVALID_PARAMETER, exit_dch); - - if (sessIdSz + args->idx > helloSz) { - ERROR_OUT(BUFFER_ERROR, exit_dch); } + if (sessIdSz + args->idx > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + ssl->session->sessionIDSz = sessIdSz; if (sessIdSz == ID_LEN) { XMEMCPY(ssl->session->sessionID, input + args->idx, sessIdSz); @@ -6516,8 +6514,13 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS13 /* legacy_cookie */ - if (ssl->options.dtls) - args->idx += OPAQUE8_LEN; + if (ssl->options.dtls) { + /* https://www.rfc-editor.org/rfc/rfc9147.html#section-5.3 */ + byte cookieLen = input[args->idx++]; + if (cookieLen != 0) { + ERROR_OUT(INVALID_PARAMETER, exit_dch); + } + } #endif /* WOLFSSL_DTLS13 */ args->clSuites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, @@ -6624,12 +6627,6 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, */ if (ext->resp == 0) { ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); -#ifdef WOLFSSL_DTLS13 - /* Send a new cookie request */ - if (ret == HRR_COOKIE_ERROR && ssl->options.dtls) - ssl->options.serverState = NULL_STATE; - else -#endif if (ret != 0) goto exit_dch; ssl->options.serverState = SERVER_HELLO_COMPLETE; @@ -6675,12 +6672,10 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_CERTS if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { WOLFSSL_MSG("Client did not send a KeyShare extension"); - SendAlert(ssl, alert_fatal, missing_extension); ERROR_OUT(INCOMPLETE_DATA, exit_dch); } if (TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS) == NULL) { WOLFSSL_MSG("Client did not send a SignatureAlgorithms extension"); - SendAlert(ssl, alert_fatal, missing_extension); ERROR_OUT(INCOMPLETE_DATA, exit_dch); } #else @@ -6706,11 +6701,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (!args->usingPSK) { if ((ret = MatchSuite(ssl, args->clSuites)) < 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) - goto exit_dch; + if (ret != WC_PENDING_E) #endif - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); - SendAlert(ssl, alert_fatal, handshake_failure); + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); goto exit_dch; } } @@ -6758,8 +6751,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.cipherSuite0 != TLS13_BYTE) { WOLFSSL_MSG("Negotiated ciphersuite from lesser version than " "TLS v1.3"); - SendAlert(ssl, alert_fatal, handshake_failure); - ERROR_OUT(VERSION_ERROR, exit_dch); + ERROR_OUT(MATCH_SUITE_ERROR, exit_dch); } #ifdef HAVE_SESSION_TICKET @@ -6781,22 +6773,12 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* switch (ssl->options.asyncState) */ #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) - /* We are using DTLSv13 and set the HRR cookie secret, use the cookie to - perform a return-routability check. */ if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie && - ssl->options.serverState < SERVER_HELLO_RETRY_REQUEST_COMPLETE) { - - /* ssl->options.serverState < SERVER_HELLO_RETRY_REQUEST_COMPLETE - so the client already provided a good KeyShareEntry. In this case - we don't add the KEY_SHARE extension to the HelloRetryRequest or - in the Cookie. The RFC8446 forbids to select a supported group - with KeyShare extension in HelloRetryRequest if the client - already provided a KeyShareEntry for that group. See rfc8446 - section 4.1.4 */ - TLSX_Remove(&ssl->extensions, TLSX_KEY_SHARE, ssl->heap); - - /* send an HRR (see wolfSSL_Accept_TLSv13()) */ - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + ssl->options.serverState <= SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + /* Cookie and key share negotiation should be handled in + * DoClientHelloStateless. If we enter here then something went wrong + * in our logic. */ + ERROR_OUT(BAD_HELLO, exit_dch); } #endif /* WOLFSSL_DTLS13 */ @@ -6820,22 +6802,6 @@ exit_dch: } #endif - if (ret == VERSION_ERROR) { -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if (((ssl->keys.dtls_sequence_number_hi == ssl->keys.curSeq_hi && - ssl->keys.dtls_sequence_number_lo < ssl->keys.curSeq_lo) || - (ssl->keys.dtls_sequence_number_hi < ssl->keys.curSeq_hi))) { - /* We should continue with the same sequence number as the - * Client Hello if available. */ - ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; - ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; - } - } -#endif - SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version); - } - FreeDch13Args(ssl, args); #ifdef WOLFSSL_ASYNC_CRYPT FreeAsyncCtx(ssl, 0); @@ -10937,6 +10903,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, { int ret = 0; word32 inIdx = *inOutIdx; + int alertType = invalid_alert; #if defined(HAVE_ECH) TLSX* echX = NULL; word32 echInOutIdx; @@ -11143,12 +11110,18 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = HashInput(ssl, input + inIdx, size); } - if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) - SendAlert(ssl, alert_fatal, decode_error); - else if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || - ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || - ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { - SendAlert(ssl, alert_fatal, illegal_parameter); + alertType = TranslateErrorToAlert(ret); + + if (alertType != invalid_alert) { +#ifdef WOLFSSL_DTLS13 + if (type == client_hello && ssl->options.dtls) { + /* We should continue with the same sequence number as the + * Client Hello. */ + ssl->dtls13EncryptEpoch->nextSeqNumber = + w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo); + } +#endif + SendAlert(ssl, alert_fatal, alertType); } if (ret == 0 && ssl->options.tls1_3) { @@ -11263,7 +11236,15 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif /* NO_WOLFSSL_SERVER */ } - WOLFSSL_LEAVE("DoTls13HandShakeMsgType", ret); +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && !ssl->options.dtlsStateful) { + DtlsResetState(ssl); + if (DtlsIgnoreError(ret)) + ret = 0; + } +#endif + + WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret); return ret; } @@ -12524,47 +12505,6 @@ const char* wolfSSL_get_cipher_name_by_hash(WOLFSSL* ssl, const char* hash) #ifndef NO_WOLFSSL_SERVER -#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) -static int DtlsAcceptStateless(WOLFSSL *ssl) -{ - int ret; - - if (!ssl->options.dtls) - return 0; - - switch (ssl->options.acceptState) { - case TLS13_ACCEPT_BEGIN: - - while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { - ret = ProcessReply(ssl); - if (ret != 0) - return ret; - } - - if (!IsAtLeastTLSv1_3(ssl->version)) - return wolfSSL_accept(ssl); - - ssl->options.acceptState = TLS13_ACCEPT_CLIENT_HELLO_DONE; - WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); - FALL_THROUGH; - - case TLS13_ACCEPT_CLIENT_HELLO_DONE: - if (ssl->options.serverState == - SERVER_HELLO_RETRY_REQUEST_COMPLETE) { - ret = SendTls13ServerHello(ssl, hello_retry_request); - DtlsResetState(ssl); - return ret; - } - - ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE; - WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); - FALL_THROUGH; - - default: - return 0; - } -} -#endif /* WOLFSSL_DTLS13 */ /* The server accepting a connection from a client. * The protocol version is expecting to be TLS v1.3. @@ -12761,19 +12701,6 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) } #endif /* WOLFSSL_DTLS13 */ -#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) - if (ssl->options.dtls && ssl->options.sendCookie) { - while (ssl->options.serverState < SERVER_HELLO_COMPLETE) { - ret = DtlsAcceptStateless(ssl); - if (ret != 0) { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } - } -#endif /* defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) */ - switch (ssl->options.acceptState) { #ifdef HAVE_SECURE_RENEGOTIATION diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4a2108a51..1764640a2 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -6071,6 +6071,7 @@ WOLFSSL_LOCAL word32 nid2oid(int nid, int grp); WOLFSSL_API int wolfSSL_DtlsUpdateWindow(word16 cur_hi, word32 cur_lo, word16* next_hi, word32* next_lo, word32 *window); WOLFSSL_LOCAL void DtlsResetState(WOLFSSL *ssl); +WOLFSSL_LOCAL int DtlsIgnoreError(int err); #endif #ifdef WOLFSSL_DTLS13 @@ -6226,6 +6227,8 @@ WOLFSSL_LOCAL int CreateCookieExt(const WOLFSSL* ssl, byte* hash, byte cipherSuite0, byte cipherSuite); #endif +WOLFSSL_LOCAL int TranslateErrorToAlert(int err); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 18c7c3a5f..4f74588ba 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -729,6 +729,7 @@ typedef struct WOLFSSL_RAND_METHOD { * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c */ enum AlertDescription { + invalid_alert = -1, close_notify = 0, unexpected_message = 10, bad_record_mac = 20, diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index 5095a32a5..d47abec87 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -170,7 +170,7 @@ WOLFSSL_API void wolfSSL_Debugging_OFF(void); WOLFSSL_API void WOLFSSL_MSG_EX(const char* fmt, ...); #define HAVE_WOLFSSL_MSG_EX #else - #define WOLFSSL_MSG_EX(...) + #define WOLFSSL_MSG_EX(...) do{} while(0) #endif WOLFSSL_API void WOLFSSL_MSG(const char* msg); WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length); From de6ed96feb188ec1a6870fcaa0d10e9c1e340c11 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 8 Feb 2023 14:31:58 +0100 Subject: [PATCH 15/29] CopyExtensions -> CopySupportedGroup --- src/dtls.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 986869749..2edf40c4e 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -433,10 +433,8 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, return 0; } -static int CopyExtensions(TLSX* src, TLSX** dst, void* heap) +static int CopySupportedGroup(TLSX* src, TLSX** dst, void* heap) { - /* Copy the following extensions - * * SupportedCurves */ TLSX* extension; int ret; @@ -545,7 +543,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, /* Set that this is a response extension */ parsedExts->resp = 1; - ret = CopyExtensions(ssl->extensions, &parsedExts, ssl->heap); + ret = CopySupportedGroup(ssl->extensions, &parsedExts, ssl->heap); if (ret != 0) goto dtls13_cleanup; From 2bbdf6979a4da113eedd2c15af4ca593efcca03f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 8 Feb 2023 14:39:30 +0100 Subject: [PATCH 16/29] Reuse ReadVector16 --- src/dtls.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 2edf40c4e..4064dec5d 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -500,7 +500,6 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, TLSX* parsedExts = NULL; WolfSSL_ConstVector tlsx; Suites suites; - word16 len; byte haveSA = 0; byte haveKS = 0; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) @@ -553,14 +552,14 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, if (ret != 0) goto dtls13_cleanup; if (tlsx.size > OPAQUE16_LEN) { - ato16(tlsx.elements, &len); - if (len != tlsx.size - OPAQUE16_LEN) + WolfSSL_ConstVector sigAlgs; + ReadVector16(tlsx.elements, &sigAlgs); + if (sigAlgs.size != tlsx.size - OPAQUE16_LEN) ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - if ((len % 2) != 0) + if ((sigAlgs.size % 2) != 0) ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); - suites.hashSigAlgoSz = len; - XMEMCPY(suites.hashSigAlgo, tlsx.elements + OPAQUE16_LEN, - len); + suites.hashSigAlgoSz = (word16)sigAlgs.size; + XMEMCPY(suites.hashSigAlgo, sigAlgs.elements, sigAlgs.size); haveSA = 1; } From 8c08dbb6ced4b478c6d9c2148ea8d2c4d79fc05e Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 8 Feb 2023 14:47:26 +0100 Subject: [PATCH 17/29] Adding checks for SigAlgs, KeyShare, and Supported Groups --- src/dtls.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 4064dec5d..289ba64b8 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -502,6 +502,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, Suites suites; byte haveSA = 0; byte haveKS = 0; + byte haveSG = 0; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) byte usePSK = 0; byte doKE = 0; @@ -573,6 +574,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, (word16)tlsx.size, 1, &parsedExts); if (ret != 0) goto dtls13_cleanup; + haveSG = 1; } /* Key share */ @@ -640,6 +642,11 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, cs.cipherSuite0 = pskInfo->cipherSuite0; cs.cipherSuite = pskInfo->cipherSuite; + if (haveSG && !haveKS) { + WOLFSSL_MSG("Client didn't send KeyShare or Supported Groups."); + ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); + } + if (doKE) { byte searched = 0; ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE, @@ -653,8 +660,9 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, else #endif { - if (!haveKS || !haveSA) { - WOLFSSL_MSG("Client didn't send KeyShare or SigAlgs"); + if (!haveKS || !haveSA || !haveSG) { + WOLFSSL_MSG("Client didn't send KeyShare or SigAlgs or " + "Supported Groups."); ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); } ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); From 5f39c594aaac94790c43fd27c54277bdfb5ff88b Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 10 Feb 2023 16:31:36 +0100 Subject: [PATCH 18/29] TLS 1.3: hold decrypted ticket to check which ciphersuite matches DTLS 1.3: Move stateless ticket decoding to FindPskSuiteFromExt --- src/dtls.c | 225 +++++++++++++++------------- src/internal.c | 361 ++++++++++++++++++++++++++++++--------------- src/tls13.c | 81 ++++------ tests/api.c | 124 ++++++++++++++++ wolfssl/internal.h | 28 +++- 5 files changed, 535 insertions(+), 284 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 289ba64b8..523f9b6df 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -291,24 +291,17 @@ static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, } #endif -#if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) +#if defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) #ifdef HAVE_SESSION_TICKET static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, - PskInfo* pskInfo, byte isTls13) + int* resume) { WolfSSL_ConstVector tlsxSessionTicket; byte tempTicket[SESSION_TICKET_LEN]; - InternalTicket* it; - int ret; + InternalTicket* it = NULL; + int ret = 0; - (void)isTls13; - -#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) - if (isTls13) - ret = TlsxFindByType(&tlsxSessionTicket, TLSX_PRE_SHARED_KEY, exts); - else -#endif - ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts); + ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts); if (ret != 0) return ret; if (tlsxSessionTicket.size == 0) @@ -316,26 +309,20 @@ static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, if (tlsxSessionTicket.size > SESSION_TICKET_LEN) return 0; XMEMCPY(tempTicket, tlsxSessionTicket.elements, tlsxSessionTicket.size); - ret = DoDecryptTicket((WOLFSSL*)ssl, tempTicket, - (word32)tlsxSessionTicket.size, &it); - if (ret != WOLFSSL_TICKET_RET_OK && ret != WOLFSSL_TICKET_RET_CREATE) - return 0; - /* Store info for later */ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - pskInfo->pv = it->pv; -#endif - pskInfo->cipherSuite0 = it->suite[0]; - pskInfo->cipherSuite = it->suite[1]; - ato16(it->namedGroup, &pskInfo->namedGroup); - - ForceZero(it, sizeof(InternalTicket)); - pskInfo->isValid = 1; + ret = DoDecryptTicket(ssl, tempTicket, (word32)tlsxSessionTicket.size, &it); + if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { + /* This logic is only for TLS <= 1.2 tickets. Don't accept TLS 1.3. */ + if (!IsAtLeastTLSv1_3(it->pv)) + *resume = TRUE; + } + if (it != NULL) + ForceZero(it, sizeof(InternalTicket)); return 0; } #endif /* HAVE_SESSION_TICKET */ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID, - PskInfo* pskInfo) + int* resume) { WOLFSSL_SESSION* sess; word32 sessRow; @@ -353,17 +340,19 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID ssl->ctx->get_sess_cb((WOLFSSL*)ssl, sessionID.elements, ID_LEN, &unused); if (sess != NULL) { - /* Store info for later */ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - pskInfo->pv = sess->version; +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + /* This logic is only for TLS <= 1.2 tickets. Don't accept + * TLS 1.3. */ + if (IsAtLeastTLSv1_3(sess->version)) + wolfSSL_FreeSession(ssl->ctx, sess); + else #endif - pskInfo->cipherSuite0 = sess->cipherSuite0; - pskInfo->cipherSuite = sess->cipherSuite; - pskInfo->namedGroup = sess->namedGroup; - - pskInfo->isValid = 1; - wolfSSL_FreeSession(ssl->ctx, sess); - return 0; + { + *resume = 1; + wolfSSL_FreeSession(ssl->ctx, sess); + return 0; + } } } if (ssl->ctx->internalCacheLookupOff) @@ -372,15 +361,15 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID #endif ret = TlsSessionCacheGetAndLock(sessionID.elements, &sess, &sessRow, 1); if (ret == 0 && sess != NULL) { - /* Store info for later */ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - pskInfo->pv = sess->version; +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + /* This logic is only for TLS <= 1.2 tickets. Don't accept + * TLS 1.3. */ + if (!IsAtLeastTLSv1_3(sess->version)) #endif - pskInfo->cipherSuite0 = sess->cipherSuite0; - pskInfo->cipherSuite = sess->cipherSuite; - pskInfo->namedGroup = sess->namedGroup; - - pskInfo->isValid = 1; + { + *resume = 1; + } TlsSessionCacheUnlockRow(sessRow); } @@ -388,19 +377,18 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID } static int TlsResumptionIsValid(const WOLFSSL* ssl, WolfSSL_CH* ch, - PskInfo* pskInfo, byte isTls13) + int* resume) { int ret; - (void)isTls13; #ifdef HAVE_SESSION_TICKET - ret = TlsTicketIsValid(ssl, ch->extension, pskInfo, isTls13); + ret = TlsTicketIsValid(ssl, ch->extension, resume); if (ret != 0) return ret; - if (pskInfo->isValid) + if (*resume) return 0; #endif /* HAVE_SESSION_TICKET */ - ret = TlsSessionIdIsValid(ssl, ch->sessionId, pskInfo); + ret = TlsSessionIdIsValid(ssl, ch->sessionId, resume); return ret; } #endif /* WOLFSSL_DTLS13 || WOLFSSL_DTLS_NO_HVR_ON_RESUME */ @@ -454,18 +442,16 @@ static int CopySupportedGroup(TLSX* src, TLSX** dst, void* heap) } #endif -#if defined(WOLFSSL_DTLS13) && !defined(NO_PSK) +#if defined(WOLFSSL_DTLS13) && \ + (!defined(NO_PSK) || defined(HAVE_SESSION_TICKET)) /* Very simplified version of CheckPreSharedKeys to find the current suite */ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, PskInfo* pskInfo, Suites* suites) { TLSX* pskExt = TLSX_Find(extensions, TLSX_PRE_SHARED_KEY); - int found = 0; PreSharedKey* current; - byte psk_key[MAX_PSK_KEY_LEN]; - word32 psk_keySz; int i; - byte foundSuite[SUITE_LEN]; + int ret; if (pskExt == NULL) return; @@ -473,17 +459,61 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, for (i = 0; i < suites->suiteSz; i += 2) { for (current = (PreSharedKey*)pskExt->data; current != NULL; current = current->next) { - if (FindPskSuite(ssl, current, psk_key, &psk_keySz, - suites->suites + i, &found, foundSuite) == 0) { - if (found) { +#ifdef HAVE_SESSION_TICKET + { + /* Decode the identity. */ + switch (current->decryptRet) { + case PSK_DECRYPT_NONE: + ret = DoClientTicket_ex(ssl, current); + break; + case PSK_DECRYPT_OK: + ret = WOLFSSL_TICKET_RET_OK; + break; + case PSK_DECRYPT_CREATE: + ret = WOLFSSL_TICKET_RET_CREATE; + break; + case PSK_DECRYPT_FAIL: + ret = WOLFSSL_TICKET_RET_REJECT; + break; + } + if (ret == WOLFSSL_TICKET_RET_OK) { + if (DoClientTicketCheck(current, ssl->timeout, + suites->suites + i) != 0) { + continue; + } + + pskInfo->cipherSuite0 = current->it->suite[0]; + pskInfo->cipherSuite = current->it->suite[1]; + pskInfo->isValid = 1; + goto cleanup; + } + } +#endif +#ifndef NO_PSK + { + int found = 0; + byte psk_key[MAX_PSK_KEY_LEN]; + word32 psk_keySz; + byte foundSuite[SUITE_LEN]; + ret = FindPskSuite(ssl, current, psk_key, &psk_keySz, + suites->suites + i, &found, foundSuite); + /* Clear the key just in case */ + ForceZero(psk_key, sizeof(psk_key)); + if (ret == 0 && found) { pskInfo->cipherSuite0 = foundSuite[0]; pskInfo->cipherSuite = foundSuite[1]; pskInfo->isValid = 1; - return; + goto cleanup; } } +#endif } } + +cleanup: +#ifdef HAVE_SESSION_TICKET + CleanupClientTickets((PreSharedKey*)pskExt->data); +#endif } #endif @@ -493,8 +523,12 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, #error "WOLFSSL_SEND_HRR_COOKIE has to be defined to use DTLS 1.3 server" #endif -static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, - PskInfo* pskInfo) +#ifdef WOLFSSL_PSK_ONE_ID +#error WOLFSSL_PSK_ONE_ID is not compatible with stateless DTLS 1.3 server. \ + wolfSSL needs to be able to make multiple calls for the same PSK. +#endif + +static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) { int ret = -1; TLSX* parsedExts = NULL; @@ -511,8 +545,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, CipherSpecs specs; byte cookieHash[WC_MAX_DIGEST_SIZE]; int cookieHashSz; - - (void)pskInfo; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + PskInfo pskInfo; + XMEMSET(&pskInfo, 0, sizeof(pskInfo)); +#endif XMEMSET(&cs, 0, sizeof(cs)); @@ -601,18 +637,13 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, * and if they don't match we will error out there anyway. */ byte modes; -#ifndef NO_PSK - /* When we didn't find a valid ticket ask the user for the - * ciphersuite matching this identity */ - if (!pskInfo->isValid) { - if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, - tlsx.elements, tlsx.size, ssl->heap) == 0) - FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites); - /* Revert to full handshake if PSK parsing failed */ - } -#endif + /* Ask the user for the ciphersuite matching this identity */ + if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts, + tlsx.elements, tlsx.size, ssl->heap) == 0) + FindPskSuiteFromExt(ssl, parsedExts, &pskInfo, &suites); + /* Revert to full handshake if PSK parsing failed */ - if (pskInfo->isValid) { + if (pskInfo.isValid) { ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, ch->extension); if (ret != 0) @@ -638,9 +669,9 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch, #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (usePSK && pskInfo->isValid) { - cs.cipherSuite0 = pskInfo->cipherSuite0; - cs.cipherSuite = pskInfo->cipherSuite; + if (usePSK && pskInfo.isValid) { + cs.cipherSuite0 = pskInfo.cipherSuite0; + cs.cipherSuite = pskInfo.cipherSuite; if (haveSG && !haveKS) { WOLFSSL_MSG("Client didn't send KeyShare or Supported Groups."); @@ -737,15 +768,13 @@ dtls13_cleanup: } #endif -static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13, - PskInfo* pskInfo) +static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13) { int ret; (void)isTls13; - (void)pskInfo; #ifdef WOLFSSL_DTLS13 if (isTls13) { - ret = SendStatelessReplyDtls13(ssl, ch, pskInfo); + ret = SendStatelessReplyDtls13(ssl, ch); } else #endif @@ -789,9 +818,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, int ret; WolfSSL_CH ch; byte isTls13 = 0; - PskInfo pskInfo; - XMEMSET(&pskInfo, 0, sizeof(pskInfo)); XMEMSET(&ch, 0, sizeof(ch)); ssl->options.dtlsStateful = 0; @@ -816,33 +843,21 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, if (ret != 0) return ret; -#if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) - ret = TlsResumptionIsValid(ssl, &ch, &pskInfo, isTls13); - if (ret != 0) - return ret; -#endif #ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME - if (pskInfo.isValid) { - ssl->options.dtlsStateful = 1; - return 0; - } -#endif - -#if defined(WOLFSSL_DTLS13) && defined(HAVE_SESSION_TICKET) - if (pskInfo.isValid) { - if (IsAtLeastTLSv1_3(pskInfo.pv)) { - if (!isTls13) - return VERSION_ERROR; - } - else { - if (isTls13) - return VERSION_ERROR; + if (!isTls13) { + int resume = FALSE; + ret = TlsResumptionIsValid(ssl, &ch, &resume); + if (ret != 0) + return ret; + if (resume) { + ssl->options.dtlsStateful = 1; + return 0; } } #endif if (ch.cookie.size == 0 && ch.cookieExt.size == 0) { - ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); + ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13); } else { byte cookieGood; @@ -857,7 +872,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, ret = INVALID_PARAMETER; else #endif - ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo); + ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13); } else ssl->options.dtlsStateful = 1; diff --git a/src/internal.c b/src/internal.c index 9d3d55fe0..67ca31535 100644 --- a/src/internal.c +++ b/src/internal.c @@ -34547,7 +34547,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } - int DoDecryptTicket(WOLFSSL* ssl, const byte* input, word32 len, + int DoDecryptTicket(const WOLFSSL* ssl, const byte* input, word32 len, InternalTicket **it) { ExternalTicket* et; @@ -34589,7 +34589,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = WOLFSSL_TICKET_RET_REJECT; } else { - ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, + /* Callback uses ssl without const but for DTLS, it really shouldn't + * modify its state. */ + ret = ssl->ctx->ticketEncCb((WOLFSSL*)ssl, et->key_name, et->iv, et->enc_ticket + inLen, 0, et->enc_ticket, inLen, &outLen, ssl->ctx->ticketEncCtx); @@ -34614,142 +34616,265 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return ret; } - /* Parse ticket sent by client, returns callback return value */ - int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len) + static int DoClientTicketCheckVersion(const WOLFSSL* ssl, + InternalTicket* it) { - InternalTicket* it; - int ret; + if (ssl->version.minor < it->pv.minor) { + WOLFSSL_MSG("Ticket has greater version"); + return VERSION_ERROR; + } + else if (ssl->version.minor > it->pv.minor) { + if (IsAtLeastTLSv1_3(it->pv) != IsAtLeastTLSv1_3(ssl->version)) { + WOLFSSL_MSG("Tickets cannot be shared between " + "TLS 1.3 and TLS 1.2 and lower"); + return VERSION_ERROR; + } + + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Ticket has lesser version"); + return VERSION_ERROR; + } + + WOLFSSL_MSG("Downgrading protocol due to ticket"); + + if (it->pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("Ticket has lesser version than allowed"); + return VERSION_ERROR; + } + } + /* Check resumption master secret. */ + if (IsAtLeastTLSv1_3(it->pv) && + it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) { + WOLFSSL_MSG("Unsupported ticketNonce len in ticket"); + return BAD_TICKET_ENCRYPT; + } + return 0; + } + + /* Return 0 when check successful. <0 on failure. */ + int DoClientTicketCheck(const PreSharedKey* psk, sword64 timeout, + const byte* suite) + { + word32 ticketAdd; +#ifdef WOLFSSL_32BIT_MILLI_TIME + word32 now; + sword64 diff; + word32 ticketSeen; /* Time ticket seen (ms) */ + + ato32(psk->it->timestamp, &ticketSeen); + + now = TimeNowInMilliseconds(); + if (now == 0) + return GETTIME_ERROR; + /* Difference between now and time ticket constructed + * (from decrypted ticket). */ + diff = now; + diff -= ticketSeen; + if (diff > timeout * 1000 || + diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) + return -1; +#else + sword64 diff; + sword64 ticketSeen; /* Time ticket seen (ms) */ + word32 seenHi, seenLo; + + ato32(psk->it->timestamp , &seenHi); + ato32(psk->it->timestamp + OPAQUE32_LEN, &seenLo); + ticketSeen = ((sword64)seenHi << 32) + seenLo; + + diff = TimeNowInMilliseconds(); + if (diff == 0) + return GETTIME_ERROR; + /* Difference between now and time ticket constructed + * (from decrypted ticket). */ + diff -= ticketSeen; + if (diff > timeout * 1000 || + diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) + return -1; +#endif + ato32(psk->it->ageAdd, &ticketAdd); + /* Subtract client's ticket age and unobfuscate. */ + diff -= psk->ticketAge; + diff += ticketAdd; + /* Check session and ticket age timeout. + * Allow +/- 1000 milliseconds on ticket age. + */ + if (diff < -1000 || diff - MAX_TICKET_AGE_DIFF * 1000 > 1000) + return -1; + +#ifndef WOLFSSL_PSK_ONE_ID + /* Check whether resumption is possible based on suites in SSL and + * ciphersuite in ticket. + */ + if (XMEMCMP(suite, psk->it->suite, SUITE_LEN) != 0) + return -1; +#else + if (!FindSuiteSSL(ssl, psk->it->suite)) + return -1; +#endif + return 0; + } + + void DoClientTicketFinalize(WOLFSSL* ssl, InternalTicket* it) + { +#ifdef WOLFSSL_TICKET_HAVE_ID + ssl->session->haveAltSessionID = 1; + XMEMCPY(ssl->session->altSessionID, it->id, ID_LEN); + if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) { + WOLFSSL_MSG("Found session matching the session id" + " found in the ticket"); + } + else { + WOLFSSL_MSG("Can't find session matching the session id" + " found in the ticket"); + } +#endif + + if (!IsAtLeastTLSv1_3(ssl->version)) { + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + /* Copy the haveExtendedMasterSecret property from the ticket to + * the saved session, so the property may be checked later. */ + ssl->session->haveEMS = it->haveEMS; + ato32((const byte*)&it->timestamp, &ssl->session->bornOn); +#ifndef NO_RESUME_SUITE_CHECK + ssl->session->cipherSuite0 = it->suite[0]; + ssl->session->cipherSuite = it->suite[1]; +#endif + } + else { +#ifdef WOLFSSL_TLS13 + /* This should have been already checked in + * DoClientTicketCheckVersion */ + if (it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) { + WOLFSSL_MSG("Unsupported ticketNonce len in ticket"); + return; + } + /* Restore information to renegotiate. */ +#ifdef WOLFSSL_32BIT_MILLI_TIME + ato32(it->timestamp, &ssl->session->ticketSeen); +#else + word32 seenHi, seenLo; + + ato32(it->timestamp , &seenHi); + ato32(it->timestamp + OPAQUE32_LEN, &seenLo); + ssl->session->ticketSeen = ((sword64)seenHi << 32) + seenLo; +#endif + ato32(it->ageAdd, &ssl->session->ticketAdd); + ssl->session->cipherSuite0 = it->suite[0]; + ssl->session->cipherSuite = it->suite[1]; +#ifdef WOLFSSL_EARLY_DATA + ato32(it->maxEarlyDataSz, &ssl->session->maxEarlyDataSz); +#endif + /* Resumption master secret. */ + XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN); +#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (ssl->session->ticketNonce.data + != ssl->session->ticketNonce.dataStatic) { + XFREE(ssl->session->ticketNonce.data, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + ssl->session->ticketNonce.data = + ssl->session->ticketNonce.dataStatic; + } +#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */ + XMEMCPY(ssl->session->ticketNonce.data, it->ticketNonce, + it->ticketNonceLen); + ssl->session->ticketNonce.len = it->ticketNonceLen; + ato16(it->namedGroup, &ssl->session->namedGroup); +#endif + } + ssl->version.minor = it->pv.minor; + } + + /* Parse ticket sent by client, returns callback return value. Doesn't + * modify ssl and stores the InternalTicket inside psk */ + int DoClientTicket_ex(const WOLFSSL* ssl, PreSharedKey* psk) + { + int decryptRet; + int ret; WOLFSSL_START(WC_FUNC_TICKET_DO); - WOLFSSL_ENTER("DoClientTicket"); + WOLFSSL_ENTER("DoClientTicket_ex"); - ret = DoDecryptTicket(ssl, input, len, &it); - if (ret != WOLFSSL_TICKET_RET_OK && ret != WOLFSSL_TICKET_RET_CREATE) { - WOLFSSL_LEAVE("DoClientTicket", ret); - return ret; + decryptRet = DoDecryptTicket(ssl, psk->identity, psk->identityLen, + &psk->it); + switch (decryptRet) { + case WOLFSSL_TICKET_RET_OK: + psk->decryptRet = PSK_DECRYPT_OK; + break; + case WOLFSSL_TICKET_RET_CREATE: + psk->decryptRet = PSK_DECRYPT_CREATE; + break; + default: + psk->decryptRet = PSK_DECRYPT_FAIL; + return decryptRet; } #ifdef WOLFSSL_CHECK_MEM_ZERO /* Internal ticket successfully decrypted. */ wc_MemZero_Add("Do Client Ticket internal", it, sizeof(InternalTicket)); #endif - /* get master secret */ - if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { - if (ssl->version.minor < it->pv.minor) { - WOLFSSL_MSG("Ticket has greater version"); - ret = VERSION_ERROR; - goto error; - } - else if (ssl->version.minor > it->pv.minor) { - if (IsAtLeastTLSv1_3(it->pv) != IsAtLeastTLSv1_3(ssl->version)) { - WOLFSSL_MSG("Tickets cannot be shared between " - "TLS 1.3 and TLS 1.2 and lower"); - ret = VERSION_ERROR; - goto error; - } + ret = DoClientTicketCheckVersion(ssl, psk->it); + if (ret != 0) { + psk->decryptRet = PSK_DECRYPT_FAIL; + return ret; + } + return decryptRet; + } - if (!ssl->options.downgrade) { - WOLFSSL_MSG("Ticket has lesser version"); - ret = VERSION_ERROR; - goto error; - } + /* Parse ticket sent by client, returns callback return value */ + int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len) + { + int decryptRet; + int ret; + InternalTicket* it - WOLFSSL_MSG("Downgrading protocol due to ticket"); + WOLFSSL_START(WC_FUNC_TICKET_DO); + WOLFSSL_ENTER("DoClientTicket"); - if (it->pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG("Ticket has lesser version than allowed"); - ret = VERSION_ERROR; - goto error; - } - ssl->version.minor = it->pv.minor; - } + decryptRet = DoDecryptTicket(ssl, input, len, &it); + if (decryptRet != WOLFSSL_TICKET_RET_OK && + decryptRet != WOLFSSL_TICKET_RET_CREATE) + return decryptRet; + #ifdef WOLFSSL_CHECK_MEM_ZERO + /* Internal ticket successfully decrypted. */ + wc_MemZero_Add("Do Client Ticket internal", it, sizeof(InternalTicket)); + #endif -#ifdef WOLFSSL_TICKET_HAVE_ID - { - ssl->session->haveAltSessionID = 1; - XMEMCPY(ssl->session->altSessionID, it->id, ID_LEN); - if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) { - WOLFSSL_MSG("Found session matching the session id" - " found in the ticket"); - } - else { - WOLFSSL_MSG("Can't find session matching the session id" - " found in the ticket"); - } - } + ret = DoClientTicketCheckVersion(ssl, it); + if (ret != 0) { + ForceZero(it, sizeof(*it)); +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(it, sizeof(InternalTicket)); +#endif + return ret; + } + + DoClientTicketFinalize(ssl, it); + + ForceZero(it, sizeof(*it)); +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(it, sizeof(InternalTicket)); #endif - if (!IsAtLeastTLSv1_3(ssl->version)) { - XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); - /* Copy the haveExtendedMasterSecret property from the ticket to - * the saved session, so the property may be checked later. */ - ssl->session->haveEMS = it->haveEMS; - ato32((const byte*)&it->timestamp, &ssl->session->bornOn); - #ifndef NO_RESUME_SUITE_CHECK - ssl->session->cipherSuite0 = it->suite[0]; - ssl->session->cipherSuite = it->suite[1]; - #endif - } - else { -#ifdef WOLFSSL_TLS13 - /* Restore information to renegotiate. */ - #ifdef WOLFSSL_32BIT_MILLI_TIME - ato32(it->timestamp, &ssl->session->ticketSeen); - #else - word32 seenHi, seenLo; + return decryptRet; + } - ato32(it->timestamp , &seenHi); - ato32(it->timestamp + OPAQUE32_LEN, &seenLo); - ssl->session->ticketSeen = ((sword64)seenHi << 32) + seenLo; - #endif - ato32(it->ageAdd, &ssl->session->ticketAdd); - ssl->session->cipherSuite0 = it->suite[0]; - ssl->session->cipherSuite = it->suite[1]; - #ifdef WOLFSSL_EARLY_DATA - ato32(it->maxEarlyDataSz, &ssl->session->maxEarlyDataSz); - #endif - /* Resumption master secret. */ - XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN); - if (it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) { - WOLFSSL_MSG("Unsupported ticketNonce len in ticket"); - WOLFSSL_LEAVE("DoClientTicket", BAD_TICKET_ENCRYPT); - return BAD_TICKET_ENCRYPT; - } -#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (ssl->session->ticketNonce.data - != ssl->session->ticketNonce.dataStatic) { - XFREE(ssl->session->ticketNonce.data, ssl->heap, - DYNAMIC_TYPE_SESSION_TICK); - ssl->session->ticketNonce.data = - ssl->session->ticketNonce.dataStatic; - } -#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */ - XMEMCPY(ssl->session->ticketNonce.data, it->ticketNonce, - it->ticketNonceLen); - ssl->session->ticketNonce.len = it->ticketNonceLen; - ato16(it->namedGroup, &ssl->session->namedGroup); + void CleanupClientTickets(PreSharedKey* psk) + { + for (; psk != NULL; psk = psk->next) { + if (psk->decryptRet == PSK_DECRYPT_OK || + psk->decryptRet == PSK_DECRYPT_CREATE) { + psk->decryptRet = PSK_DECRYPT_NONE; + ForceZero(psk->identity, psk->identityLen); +#ifdef WOLFSSL_CHECK_MEM_ZERO + /* We want to check the InternalTicket area since that is what + * we registered in DoClientTicket_ex */ + wc_MemZero_Check((((ExternalTicket*)psk->identity)->enc_ticket), + sizeof(InternalTicket)); #endif } } - - ForceZero(it, sizeof(*it)); -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Check(it, sizeof(InternalTicket)); -#endif - - WOLFSSL_LEAVE("DoClientTicket", ret); - WOLFSSL_END(WC_FUNC_TICKET_DO); - - return ret; - -error: - ForceZero(it, sizeof(*it)); -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Check(it, sizeof(InternalTicket)); -#endif - WOLFSSL_ERROR_VERBOSE(ret); - return WOLFSSL_TICKET_RET_REJECT; } diff --git a/src/tls13.c b/src/tls13.c index f5ecf1dd6..876df789b 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5658,68 +5658,33 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, #ifdef HAVE_SESSION_TICKET /* Decode the identity. */ - ret = DoClientTicket(ssl, current->identity, current->identityLen); + switch (current->decryptRet) { + case PSK_DECRYPT_NONE: + ret = DoClientTicket_ex(ssl, current); + break; + case PSK_DECRYPT_OK: + ret = WOLFSSL_TICKET_RET_OK; + break; + case PSK_DECRYPT_CREATE: + ret = WOLFSSL_TICKET_RET_CREATE; + break; + case PSK_DECRYPT_FAIL: + ret = WOLFSSL_TICKET_RET_REJECT; + break; + } + #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) return ret; #endif if (ret == WOLFSSL_TICKET_RET_OK) { - #ifdef WOLFSSL_32BIT_MILLI_TIME - word32 now; - sword64 diff; - - now = TimeNowInMilliseconds(); - if (now == 0) - return GETTIME_ERROR; - /* Difference between now and time ticket constructed - * (from decrypted ticket). */ - diff = now; - diff -= ssl->session->ticketSeen; - if (diff > (sword64)ssl->timeout * 1000 || - diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) { + if (DoClientTicketCheck(current, ssl->timeout, suite) != 0) { + current = current->next; continue; } - #else - sword64 diff; - diff = TimeNowInMilliseconds(); - if (diff == 0) - return GETTIME_ERROR; - /* Difference between now and time ticket constructed - * (from decrypted ticket). */ - diff -= ssl->session->ticketSeen; - if (diff > (sword64)ssl->timeout * 1000 || - diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) { - continue; - } - #endif - /* Subtract client's ticket age and unobfuscate. */ - diff -= current->ticketAge; - diff += ssl->session->ticketAdd; - /* Check session and ticket age timeout. - * Allow +/- 1000 milliseconds on ticket age. - */ - if (diff < -1000 || diff - MAX_TICKET_AGE_DIFF * 1000 > 1000) - continue; - - #if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK) - /* Check whether resumption is possible based on suites in SSL and - * ciphersuite in ticket. - */ - if ((suite[0] != ssl->session->cipherSuite0) || - (suite[1] != ssl->session->cipherSuite)) - continue; - #else - { - byte s[2] = { - ssl->session->cipherSuite0, - ssl->session->cipherSuite, - }; - if (!FindSuiteSSL(ssl, s)) - continue; - } - #endif + DoClientTicketFinalize(ssl, current->it); /* SERVER: using secret in session ticket for peer auth. */ ssl->options.peerAuthGood = 1; @@ -5893,13 +5858,23 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, ret = DoPreSharedKeys(ssl, input, helloSz - bindersLen, suites->suites + i, usingPSK, &first); if (ret != 0) { +#ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) +#endif + CleanupClientTickets((PreSharedKey*)ext->data); +#endif WOLFSSL_MSG_EX("DoPreSharedKeys: %d", ret); return ret; } } +#ifdef HAVE_SESSION_TICKET + CleanupClientTickets((PreSharedKey*)ext->data); +#endif #else ret = DoPreSharedKeys(ssl, input, helloSz - bindersLen, suite, usingPSK, &first); + CleanupClientTickets((PreSharedKey*)ext->data); if (ret != 0) { WOLFSSL_MSG_EX("DoPreSharedKeys: %d", ret); return ret; diff --git a/tests/api.c b/tests/api.c index 3c0fc66d1..9fa4fc528 100644 --- a/tests/api.c +++ b/tests/api.c @@ -62844,6 +62844,129 @@ static int test_wolfSSL_CRL_CERT_REVOKED_alert(void) } #endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) \ + && defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_AESGCM) && \ + !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ + defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + +static WOLFSSL_CTX* test_TLS_13_ticket_different_ciphers_ctx = NULL; +static WOLFSSL_SESSION* test_TLS_13_ticket_different_ciphers_session = NULL; +static int test_TLS_13_ticket_different_ciphers_run = 0; + +static void test_TLS_13_ticket_different_ciphers_ssl_ready(WOLFSSL* ssl) +{ + switch (test_TLS_13_ticket_different_ciphers_run) { + case 0: + /* First run */ + AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES128-GCM-SHA256"), + WOLFSSL_SUCCESS); + if (wolfSSL_is_server(ssl)) { + AssertNotNull(test_TLS_13_ticket_different_ciphers_ctx = + wolfSSL_get_SSL_CTX(ssl)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_up_ref(test_TLS_13_ticket_different_ciphers_ctx)); + } + break; + case 1: + /* Second run */ + AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384:" + "TLS13-AES128-GCM-SHA256"), + WOLFSSL_SUCCESS); + if (!wolfSSL_is_server(ssl)) { + AssertIntEQ(wolfSSL_set_session(ssl, + test_TLS_13_ticket_different_ciphers_session), + WOLFSSL_SUCCESS); + } + break; + default: + /* Bad state? */ + Fail(("Should not enter here"), ("Should not enter here")); + } +} + +static void test_TLS_13_ticket_different_ciphers_on_result(WOLFSSL* ssl) +{ + switch (test_TLS_13_ticket_different_ciphers_run) { + case 0: + /* First run */ + AssertNotNull(test_TLS_13_ticket_different_ciphers_session = + wolfSSL_get1_session(ssl)); + break; + case 1: + /* Second run */ + AssertTrue(wolfSSL_session_reused(ssl)); + break; + default: + /* Bad state? */ + Fail(("Should not enter here"), ("Should not enter here")); + } +} + +static int test_TLS_13_ticket_different_ciphers(void) +{ + /* Check that we handle the connection when the ticket doesn't match + * the first ciphersuite. */ + callback_functions client_cbs, server_cbs; + struct test_params { + method_provider client_meth; + method_provider server_meth; + int doUdp; + } params[] = { +#ifdef WOLFSSL_DTLS13 + /* Test that the stateless code handles sessions correctly */ + {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, 1}, +#endif + {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, 0}, + }; + size_t i; + + for (i = 0; i < sizeof(params)/sizeof(*params); i++) { + XMEMSET(&client_cbs, 0, sizeof(client_cbs)); + XMEMSET(&server_cbs, 0, sizeof(server_cbs)); + + test_TLS_13_ticket_different_ciphers_run = 0; + + client_cbs.doUdp = server_cbs.doUdp = params[i].doUdp; + + client_cbs.method = params[i].client_meth; + server_cbs.method = params[i].server_meth; + + client_cbs.ssl_ready = test_TLS_13_ticket_different_ciphers_ssl_ready; + server_cbs.ssl_ready = test_TLS_13_ticket_different_ciphers_ssl_ready; + + client_cbs.on_result = test_TLS_13_ticket_different_ciphers_on_result; + + server_cbs.ticNoInit = 1; + + test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); + + AssertTrue(client_cbs.return_code); + AssertTrue(server_cbs.return_code); + + test_TLS_13_ticket_different_ciphers_run++; + + server_cbs.ctx = test_TLS_13_ticket_different_ciphers_ctx; + + test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); + + AssertTrue(client_cbs.return_code); + AssertTrue(server_cbs.return_code); + + wolfSSL_SESSION_free(test_TLS_13_ticket_different_ciphers_session); + test_TLS_13_ticket_different_ciphers_session = NULL; + wolfSSL_CTX_free(test_TLS_13_ticket_different_ciphers_ctx); + test_TLS_13_ticket_different_ciphers_ctx = NULL; + } + + return TEST_RES_CHECK(1); +} +#else +static int test_TLS_13_ticket_different_ciphers(void) +{ + return TEST_SKIPPED; +} +#endif + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -63844,6 +63967,7 @@ TEST_CASE testCases[] = { * !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) */ TEST_DECL(test_wolfSSL_CTX_set_ciphersuites), TEST_DECL(test_wolfSSL_CRL_CERT_REVOKED_alert), + TEST_DECL(test_TLS_13_ticket_different_ciphers), TEST_DECL(test_WOLFSSL_dtls_version_alert), TEST_DECL(test_ForceZero), diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 1764640a2..5652f7c2c 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3097,6 +3097,13 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl, #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +enum PskDecryptReturn { + PSK_DECRYPT_NONE = 0, + PSK_DECRYPT_OK, + PSK_DECRYPT_CREATE, + PSK_DECRYPT_FAIL, +}; + /* The PreSharedKey extension information - entry in a linked list. */ typedef struct PreSharedKey { word16 identityLen; /* Length of identity */ @@ -3107,8 +3114,12 @@ typedef struct PreSharedKey { word32 binderLen; /* Length of HMAC */ byte binder[WC_MAX_DIGEST_SIZE]; /* HMAC of handshake */ byte hmac; /* HMAC algorithm */ +#ifdef HAVE_SESSION_TICKET + InternalTicket* it; /* ptr to ticket */ +#endif byte resumption:1; /* Resumption PSK */ byte chosen:1; /* Server's choice */ + byte decryptRet:3; /* Ticket decrypt return */ struct PreSharedKey* next; /* List pointer */ } PreSharedKey; @@ -3933,13 +3944,8 @@ typedef struct TicketNonce { #ifdef WOLFSSL_DTLS typedef struct PskInfo { -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - /* Macro guard matches one for session->version */ - ProtocolVersion pv; -#endif byte cipherSuite0; byte cipherSuite; - word16 namedGroup; byte isValid:1; } PskInfo; #endif @@ -5650,10 +5656,16 @@ extern const WOLF_EC_NIST_NAME kNistCurves[]; WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL* ssl); WOLFSSL_LOCAL int SendTicket(WOLFSSL* ssl); #ifdef HAVE_SESSION_TICKET -WOLFSSL_LOCAL int DoDecryptTicket(WOLFSSL* ssl, const byte* input, word32 len, - InternalTicket **it); -#endif /* HAVE_SESSION_TICKET */ +WOLFSSL_LOCAL int DoDecryptTicket(const WOLFSSL* ssl, const byte* input, + word32 len, InternalTicket **it); +/* Return 0 when check successful. <0 on failure. */ +WOLFSSL_LOCAL int DoClientTicketCheck(const PreSharedKey* psk, sword64 timeout, + const byte* suite); +WOLFSSL_LOCAL void DoClientTicketFinalize(WOLFSSL* ssl, InternalTicket* it); +WOLFSSL_LOCAL void CleanupClientTickets(PreSharedKey* psk); WOLFSSL_LOCAL int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len); +WOLFSSL_LOCAL int DoClientTicket_ex(const WOLFSSL* ssl, PreSharedKey* psk); +#endif /* HAVE_SESSION_TICKET */ WOLFSSL_LOCAL int SendData(WOLFSSL* ssl, const void* data, int sz); #ifdef WOLFSSL_TLS13 WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType); From 61c2059cd97087e7d58f61a7204601443c6dbe3a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 13 Feb 2023 14:48:44 +0100 Subject: [PATCH 19/29] Differentiate between empty and missing extension --- src/dtls.c | 52 +++++++++++++++++++++++++++++++++------------- src/tls13.c | 5 +---- wolfssl/internal.h | 8 ------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 523f9b6df..7341b967f 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -115,6 +115,15 @@ int DtlsIgnoreError(int err) #define DTLS_COOKIE_SZ WC_SHA256_DIGEST_SIZE #endif /* !NO_SHA256 */ +#if defined(WOLFSSL_DTLS13) && (defined(HAVE_SESSION_TICKET) || \ + !defined(NO_PSK)) +typedef struct PskInfo { + byte cipherSuite0; + byte cipherSuite; + byte isValid:1; +} PskInfo; +#endif + typedef struct WolfSSL_ConstVector { word32 size; const byte* elements; @@ -266,7 +275,7 @@ static int ParseClientHello(const byte* input, word32 helloSz, WolfSSL_CH* ch) #if (defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) && defined(HAVE_SESSION_TICKET)) \ || defined(WOLFSSL_DTLS13) static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, - WolfSSL_ConstVector exts) + WolfSSL_ConstVector exts, int* tlsxFound) { word32 len, idx = 0; word16 type; @@ -274,6 +283,7 @@ static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, XMEMSET(ret, 0, sizeof(*ret)); len = exts.size; + *tlsxFound = FALSE; /* type + len */ while (len >= OPAQUE16_LEN + OPAQUE16_LEN) { ato16(exts.elements + idx, &type); @@ -283,6 +293,7 @@ static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, return BUFFER_ERROR; if (type == extType) { XMEMCPY(ret, &ext, sizeof(ext)); + *tlsxFound = TRUE; return 0; } len = exts.size - idx; @@ -300,8 +311,10 @@ static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, byte tempTicket[SESSION_TICKET_LEN]; InternalTicket* it = NULL; int ret = 0; + int tlsxFound; - ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts); + ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts, + &tlsxFound); if (ret != 0) return ret; if (tlsxSessionTicket.size == 0) @@ -400,12 +413,13 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, WolfSSL_ConstVector tlsxSupportedVersions; int ret; ProtocolVersion pv = ssl->version; + int tlsxFound; ret = TlsxFindByType(&tlsxSupportedVersions, TLSX_SUPPORTED_VERSIONS, - ch->extension); + ch->extension, &tlsxFound); if (ret != 0) return ret; - if (tlsxSupportedVersions.size == 0) { + if (!tlsxFound) { *isTls13 = 0; return 0; } @@ -473,6 +487,7 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, ret = WOLFSSL_TICKET_RET_CREATE; break; case PSK_DECRYPT_FAIL: + default: ret = WOLFSSL_TICKET_RET_REJECT; break; } @@ -510,10 +525,12 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, } } + /* Empty return necessary so we can have both the label and macro guard */ cleanup: #ifdef HAVE_SESSION_TICKET CleanupClientTickets((PreSharedKey*)pskExt->data); #endif + return; } #endif @@ -533,6 +550,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) int ret = -1; TLSX* parsedExts = NULL; WolfSSL_ConstVector tlsx; + int tlsxFound; Suites suites; byte haveSA = 0; byte haveKS = 0; @@ -585,11 +603,13 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* Signature algs */ ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, - ch->extension); + ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; - if (tlsx.size > OPAQUE16_LEN) { + if (tlsxFound) { WolfSSL_ConstVector sigAlgs; + if (tlsx.size < OPAQUE16_LEN) + ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); ReadVector16(tlsx.elements, &sigAlgs); if (sigAlgs.size != tlsx.size - OPAQUE16_LEN) ERROR_OUT(BUFFER_ERROR, dtls13_cleanup); @@ -602,10 +622,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* Supported groups */ ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, - ch->extension); + ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; - if (tlsx.size != 0) { + if (tlsxFound) { ret = TLSX_SupportedCurve_Parse(ssl, tlsx.elements, (word16)tlsx.size, 1, &parsedExts); if (ret != 0) @@ -615,10 +635,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* Key share */ ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, - ch->extension); + ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; - if (tlsx.size != 0) { + if (tlsxFound) { ret = TLSX_KeyShare_Parse_ClientHello(ssl, tlsx.elements, (word16)tlsx.size, &parsedExts); if (ret != 0) @@ -628,10 +648,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Pre-shared key */ - ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension); + ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; - if (tlsx.size != 0) { + if (tlsxFound) { /* Let's just assume that the binders are correct here. We will * actually verify this in the stateful part of the processing * and if they don't match we will error out there anyway. */ @@ -645,10 +665,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) if (pskInfo.isValid) { ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, - ch->extension); + ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; - if (tlsx.size == 0) + if (!tlsxFound) ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup); ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size, client_hello, &modes); @@ -832,7 +852,9 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, if (ret != 0) return ret; if (isTls13) { - ret = TlsxFindByType(&ch.cookieExt, TLSX_COOKIE, ch.extension); + int tlsxFound; + ret = TlsxFindByType(&ch.cookieExt, TLSX_COOKIE, ch.extension, + &tlsxFound); if (ret != 0) return ret; } diff --git a/src/tls13.c b/src/tls13.c index 876df789b..e5747e933 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4404,10 +4404,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) if (ssl->options.dtls) { ret = Dtls13HandshakeSend(ssl, args->output, (word16)args->sendSz, (word16)args->idx, client_hello, 0); - - WOLFSSL_LEAVE("SendTls13ClientHello", ret); - WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); - return ret; + break; } #endif /* WOLFSSL_DTLS13 */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 5652f7c2c..ba27555cd 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3942,14 +3942,6 @@ typedef struct TicketNonce { #endif -#ifdef WOLFSSL_DTLS -typedef struct PskInfo { - byte cipherSuite0; - byte cipherSuite; - byte isValid:1; -} PskInfo; -#endif - /* wolfSSL session type */ struct WOLFSSL_SESSION { /* WARNING Do not add fields here. They will be ignored in From 885cca67feda3ff239c5911670263675f4421ab4 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Mon, 13 Feb 2023 16:14:51 +0100 Subject: [PATCH 20/29] Check for shared ctx in all configs --- tests/api.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/api.c b/tests/api.c index 9fa4fc528..0911ba943 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5149,13 +5149,11 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) opts->return_code = TEST_FAIL; cbf = opts->callbacks; -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (cbf != NULL && cbf->ctx) { ctx = cbf->ctx; sharedCtx = 1; } else -#endif { WOLFSSL_METHOD* method = NULL; if (cbf != NULL && cbf->method != NULL) { From b0d7656ad2c4a3f514c894216b21b7019dbdf301 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 15 Feb 2023 16:32:50 +0100 Subject: [PATCH 21/29] Rebase fixes --- src/crl.c | 2 +- src/dtls.c | 2 +- src/internal.c | 10 +++++++--- src/ssl.c | 4 ++-- src/tls13.c | 8 +++----- tests/api.c | 3 ++- wolfssl/internal.h | 7 ++++--- 7 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/crl.c b/src/crl.c index 9e980e97e..76a7a67f2 100644 --- a/src/crl.c +++ b/src/crl.c @@ -1446,7 +1446,7 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) pathLen = (word32)XSTRLEN(path); pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); if (pathBuf) { - XSTRNCPY(pathBuf, path, pathLen+1); + XMEMCPY(pathBuf, path, pathLen+1); if (type == WOLFSSL_FILETYPE_PEM) { /* free old path before setting a new one */ diff --git a/src/dtls.c b/src/dtls.c index 7341b967f..dfb3ece12 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -492,7 +492,7 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions, break; } if (ret == WOLFSSL_TICKET_RET_OK) { - if (DoClientTicketCheck(current, ssl->timeout, + if (DoClientTicketCheck(ssl, current, ssl->timeout, suites->suites + i) != 0) { continue; } diff --git a/src/internal.c b/src/internal.c index 67ca31535..c0e98e45c 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6691,6 +6691,8 @@ int ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) (void)ctx; ssl->options.shutdownDone = 0; + if (ssl->session != NULL) + ssl->session->side = (byte)ssl->options.side; return ret; } @@ -34652,8 +34654,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Return 0 when check successful. <0 on failure. */ - int DoClientTicketCheck(const PreSharedKey* psk, sword64 timeout, - const byte* suite) + int DoClientTicketCheck(const WOLFSSL* ssl, const PreSharedKey* psk, + sword64 timeout, const byte* suite) { word32 ticketAdd; #ifdef WOLFSSL_32BIT_MILLI_TIME @@ -34702,13 +34704,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (diff < -1000 || diff - MAX_TICKET_AGE_DIFF * 1000 > 1000) return -1; -#ifndef WOLFSSL_PSK_ONE_ID +#if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK) /* Check whether resumption is possible based on suites in SSL and * ciphersuite in ticket. */ + (void)ssl; if (XMEMCMP(suite, psk->it->suite, SUITE_LEN) != 0) return -1; #else + (void)suite; if (!FindSuiteSSL(ssl, psk->it->suite)) return -1; #endif diff --git a/src/ssl.c b/src/ssl.c index adc3c1eb4..3a5e7d98a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15035,8 +15035,8 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) } else { #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) - WOLFSSL_MSG("Session is expired but return success for \ - OpenSSL compatibility"); + WOLFSSL_MSG("Session is expired but return success for " + "OpenSSL compatibility"); ret = WOLFSSL_SUCCESS; #else ret = WOLFSSL_FAILURE; /* session timed out */ diff --git a/src/tls13.c b/src/tls13.c index e5747e933..c05421701 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3242,14 +3242,14 @@ exit_buildmsg: #if !defined(NO_WOLFSSL_CLIENT) || (!defined(NO_WOLFSSL_SERVER) && \ (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ - defined(WOLFSSL_PSK_ONE_ID)) \ + (defined(WOLFSSL_PSK_ONE_ID) || defined(WOLFSSL_PRIORITIZE_PSK))) /* Find the cipher suite in the suites set in the SSL. * * ssl SSL/TLS object. * suite Cipher suite to look for. * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise. */ -static int FindSuiteSSL(const WOLFSSL* ssl, byte* suite) +int FindSuiteSSL(const WOLFSSL* ssl, byte* suite) { word16 i; const Suites* suites = WOLFSSL_SUITES(ssl); @@ -5676,10 +5676,8 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, #endif if (ret == WOLFSSL_TICKET_RET_OK) { - if (DoClientTicketCheck(current, ssl->timeout, suite) != 0) { - current = current->next; + if (DoClientTicketCheck(ssl, current, ssl->timeout, suite) != 0) continue; - } DoClientTicketFinalize(ssl, current->it); diff --git a/tests/api.c b/tests/api.c index 0911ba943..c4182ccbf 100644 --- a/tests/api.c +++ b/tests/api.c @@ -62845,7 +62845,8 @@ static int test_wolfSSL_CRL_CERT_REVOKED_alert(void) #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) \ && defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_AESGCM) && \ !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ - defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) && \ + !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) static WOLFSSL_CTX* test_TLS_13_ticket_different_ciphers_ctx = NULL; static WOLFSSL_SESSION* test_TLS_13_ticket_different_ciphers_session = NULL; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ba27555cd..8482b55ab 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -5651,8 +5651,8 @@ WOLFSSL_LOCAL int SendTicket(WOLFSSL* ssl); WOLFSSL_LOCAL int DoDecryptTicket(const WOLFSSL* ssl, const byte* input, word32 len, InternalTicket **it); /* Return 0 when check successful. <0 on failure. */ -WOLFSSL_LOCAL int DoClientTicketCheck(const PreSharedKey* psk, sword64 timeout, - const byte* suite); +WOLFSSL_LOCAL int DoClientTicketCheck(const WOLFSSL* ssl, + const PreSharedKey* psk, sword64 timeout, const byte* suite); WOLFSSL_LOCAL void DoClientTicketFinalize(WOLFSSL* ssl, InternalTicket* it); WOLFSSL_LOCAL void CleanupClientTickets(PreSharedKey* psk); WOLFSSL_LOCAL int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len); @@ -5892,10 +5892,11 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); WOLFSSL_LOCAL sword64 TimeNowInMilliseconds(void); #endif - WOLFSSL_LOCAL int FindSuiteMac(WOLFSSL* ssl, byte* suite); #endif WOLFSSL_LOCAL word32 LowResTimer(void); +WOLFSSL_LOCAL int FindSuiteSSL(const WOLFSSL* ssl, byte* suite); + #ifndef NO_CERTS WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag, void* heap); From f2032e8744b6515665feed6b34cc2d15df17fcf9 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 21 Feb 2023 13:23:00 +0100 Subject: [PATCH 22/29] Clear decrypted ticket that failed checks in DoClientTicket_ex --- src/internal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/internal.c b/src/internal.c index c0e98e45c..ee6d4c3c7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -34821,6 +34821,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = DoClientTicketCheckVersion(ssl, psk->it); if (ret != 0) { psk->decryptRet = PSK_DECRYPT_FAIL; + ForceZero(psk->identity, psk->identityLen); +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(psk->it, sizeof(InternalTicket)); +#endif return ret; } return decryptRet; From 06749144d5f864cdceef69c811b1e0a50f7a64f1 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 21 Feb 2023 14:17:19 +0100 Subject: [PATCH 23/29] Add RFC link to help understand constraints --- src/dtls.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index dfb3ece12..da1883129 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -693,8 +693,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) cs.cipherSuite0 = pskInfo.cipherSuite0; cs.cipherSuite = pskInfo.cipherSuite; - if (haveSG && !haveKS) { - WOLFSSL_MSG("Client didn't send KeyShare or Supported Groups."); + /* https://datatracker.ietf.org/doc/html/rfc8446#section-9.2 */ + if (haveSG ^ haveKS) { + WOLFSSL_MSG("Client needs to send both or none of KeyShare and " + "SupportedGroups"); ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); } @@ -711,9 +713,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) else #endif { + /* https://datatracker.ietf.org/doc/html/rfc8446#section-9.2 */ if (!haveKS || !haveSA || !haveSG) { WOLFSSL_MSG("Client didn't send KeyShare or SigAlgs or " - "Supported Groups."); + "SupportedGroups."); ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); } ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); From cbedae2f55126a5b8d67bfcbec98c16e5aff0c19 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 21 Feb 2023 14:17:44 +0100 Subject: [PATCH 24/29] This path in TLSX_KeyShare_Choose should not be taken normally --- src/tls.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tls.c b/src/tls.c index 399890938..9a68fe13d 100644 --- a/src/tls.c +++ b/src/tls.c @@ -9110,13 +9110,14 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, list = (KeyShareEntry*)extension->data; if (extension && extension->resp == 1) { - int ret = 0; + /* Outside of the async case this path should not be taken. */ + int ret = INCOMPLETE_DATA; #ifdef WOLFSSL_ASYNC_CRYPT /* in async case make sure key generation is finalized */ serverKSE = (KeyShareEntry*)extension->data; - if (serverKSE->lastRet == WC_PENDING_E) { + if (serverKSE && serverKSE->lastRet == WC_PENDING_E) { if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) - *doHelloRetry = 1; + *searched = 1; ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE); } #endif From db1f199a1128acb32ac1f42e86bb4b59384976f8 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 21 Feb 2023 14:37:20 +0100 Subject: [PATCH 25/29] Add comment about keyshare negotiation --- src/dtls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dtls.c b/src/dtls.c index da1883129..4238d55ad 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -719,6 +719,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) "SupportedGroups."); ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); } + /* TLSX_KeyShare_Choose is done deep inside MatchSuite_ex */ ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); if (ret < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); From a432502a98ed63b16997229e47b98583d143ef0e Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 21 Feb 2023 18:25:18 +0100 Subject: [PATCH 26/29] Refactor sequence number reset for DTLS into one function --- src/dtls.c | 20 ++++++++++++++++++++ src/internal.c | 9 +-------- src/tls13.c | 8 ++------ wolfssl/internal.h | 1 + 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index 4238d55ad..ce84fd3a0 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -99,6 +99,26 @@ int DtlsIgnoreError(int err) } } +void DtlsSetSeqNumForReply(WOLFSSL* ssl) +{ + /* We cover both DTLS 1.2 and 1.3 cases because we may be negotiating + * protocols. */ + /* We should continue with the same sequence number as the + * Client Hello. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; +#ifdef WOLFSSL_DTLS13 + if (ssl->dtls13EncryptEpoch != NULL) { + ssl->dtls13EncryptEpoch->nextSeqNumber = + w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo); + } +#endif + /* We should continue with the same handshake number as the + * Client Hello. */ + ssl->keys.dtls_handshake_number = + ssl->keys.dtls_peer_handshake_number; +} + #if !defined(NO_WOLFSSL_SERVER) #if defined(NO_SHA) && defined(NO_SHA256) diff --git a/src/internal.c b/src/internal.c index ee6d4c3c7..35ba423bd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -33186,14 +33186,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Update the ssl->options.dtlsStateful setting `if` statement in * wolfSSL_accept when changing this one. */ if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl)) { - /* We should continue with the same sequence number as the - * Client Hello. */ - ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; - ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; - /* We should continue with the same handshake number as the - * Client Hello. */ - ssl->keys.dtls_handshake_number = - ssl->keys.dtls_peer_handshake_number; + DtlsSetSeqNumForReply(ssl); ret = DoClientHelloStateless(ssl, input, inOutIdx, helloSz); if (ret != 0 || !ssl->options.dtlsStateful) { int alertType = TranslateErrorToAlert(ret); diff --git a/src/tls13.c b/src/tls13.c index c05421701..44b0ec687 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -11084,12 +11084,8 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (alertType != invalid_alert) { #ifdef WOLFSSL_DTLS13 - if (type == client_hello && ssl->options.dtls) { - /* We should continue with the same sequence number as the - * Client Hello. */ - ssl->dtls13EncryptEpoch->nextSeqNumber = - w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo); - } + if (type == client_hello && ssl->options.dtls) + DtlsSetSeqNumForReply(ssl); #endif SendAlert(ssl, alert_fatal, alertType); } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 8482b55ab..3b0bc62c8 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -6077,6 +6077,7 @@ WOLFSSL_API int wolfSSL_DtlsUpdateWindow(word16 cur_hi, word32 cur_lo, word16* next_hi, word32* next_lo, word32 *window); WOLFSSL_LOCAL void DtlsResetState(WOLFSSL *ssl); WOLFSSL_LOCAL int DtlsIgnoreError(int err); +WOLFSSL_LOCAL void DtlsSetSeqNumForReply(WOLFSSL* ssl); #endif #ifdef WOLFSSL_DTLS13 From f5f67f43d7ba95317cf65711db0792dbdc048f19 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 21 Feb 2023 20:11:54 +0100 Subject: [PATCH 27/29] Reset DTLS sequence number --- src/dtls.c | 2 ++ tests/api.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index ce84fd3a0..c517bf895 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -66,6 +66,8 @@ void DtlsResetState(WOLFSSL* ssl) #endif ssl->keys.dtls_expected_peer_handshake_number = 0; ssl->keys.dtls_handshake_number = 0; + ssl->keys.dtls_sequence_number_hi = 0; + ssl->keys.dtls_sequence_number_lo = 0; /* Reset states */ ssl->options.serverState = NULL_STATE; diff --git a/tests/api.c b/tests/api.c index c4182ccbf..5f02f9f61 100644 --- a/tests/api.c +++ b/tests/api.c @@ -59319,7 +59319,7 @@ static void test_wolfSSL_dtls_send_ch_with_invalid_cookie(WOLFSSL* ssl) } #endif -static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(WOLFSSL* ssl) +static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl) { #ifndef NO_MD5 enum wc_HashType hashType = WC_HASH_TYPE_MD5; @@ -59332,7 +59332,7 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(WOLFSSL* ssl) #endif byte hashBuf[WC_MAX_DIGEST_SIZE]; wc_HashAlg hash; - TLSX* exts = ssl->extensions; + const TLSX* exts = ssl->extensions; WOLFSSL sslCopy; /* Use a copy to omit certain fields */ HS_Hashes* hsHashes = ssl->hsHashes; /* Is re-allocated in * InitHandshakeHashes */ From 335722c586d894c49c5317333a25b67e101d61c6 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 22 Feb 2023 09:46:02 +0100 Subject: [PATCH 28/29] Async fixes --- src/dtls.c | 2 +- src/dtls13.c | 6 +++-- src/internal.c | 2 +- src/tls.c | 60 +++++++++++++++++++++++++++++-------------- src/tls13.c | 64 ++++++++++++++++++++++++++++++++++------------ tests/api.c | 6 +++++ wolfssl/internal.h | 8 ++++-- 7 files changed, 107 insertions(+), 41 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index c517bf895..fda5a8957 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -744,7 +744,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* TLSX_KeyShare_Choose is done deep inside MatchSuite_ex */ ret = MatchSuite_ex(ssl, &suites, &cs, parsedExts); if (ret < 0) { - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + WOLFSSL_MSG("Unsupported cipher suite, ClientHello DTLS 1.3"); ERROR_OUT(INCOMPLETE_DATA, dtls13_cleanup); } } diff --git a/src/dtls13.c b/src/dtls13.c index aa0da54b0..6149031f5 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -363,8 +363,10 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) msg->sz, msg->sz); /* processing certificate_request triggers a connect. The error came - * from there, the message can be considered processed successfully */ - if (ret == 0 || (msg->type == certificate_request && + * from there, the message can be considered processed successfully. + * WANT_WRITE means that we are done with processing the msg and we are + * waiting to flush the output buffer. */ + if ((ret == 0 || ret == WANT_WRITE) || (msg->type == certificate_request && ssl->options.handShakeDone && ret == WC_PENDING_E)) { Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type); diff --git a/src/internal.c b/src/internal.c index 35ba423bd..aad2ae532 100644 --- a/src/internal.c +++ b/src/internal.c @@ -20125,7 +20125,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ) { /* Shrink input buffer when we successfully finish record * processing */ - if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) + if ((ret == 0) && ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, NO_FORCED_FREE); return ret; } diff --git a/src/tls.c b/src/tls.c index 9a68fe13d..541f60900 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7393,7 +7393,7 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) * ssl The SSL/TLS object. * kse The key share entry holding peer data. */ -static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) +int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) { int ret; /* Named FFDHE groups have a bit set to identify them. */ @@ -9027,6 +9027,7 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions) TLSX* extension; SupportedCurve* curve = NULL; SupportedCurve* preferredCurve = NULL; + KeyShareEntry* kse = NULL; int preferredRank = WOLFSSL_MAX_GROUP_COUNT; int rank; @@ -9055,27 +9056,32 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions) return BAD_KEY_SHARE_DATA; } - /* Delete the old key share data list. */ + #ifdef WOLFSSL_ASYNC_CRYPT + /* Check the old key share data list. */ extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); if (extension != NULL) { - KeyShareEntry* kse = (KeyShareEntry*)extension->data; - #ifdef WOLFSSL_ASYNC_CRYPT - /* for async don't free, call `TLSX_KeyShare_Use` again */ - if (kse && kse->lastRet != WC_PENDING_E) - #endif - { - TLSX_KeyShare_FreeAll(kse, ssl->heap); - extension->data = NULL; + kse = (KeyShareEntry*)extension->data; + /* We should not be computing keys if we are only going to advertise + * our choice here. */ + if (kse != NULL && kse->lastRet == WC_PENDING_E) { + WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA); + return BAD_KEY_SHARE_DATA; } } + #endif - /* Add in the chosen group. */ - ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL, extensions); - if (ret != 0 && ret != WC_PENDING_E) + /* Push new KeyShare extension. This will also free the old one */ + ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + /* Extension got pushed to head */ + extension = *extensions; + /* Push the selected curve */ + ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, curve->name, + ssl->heap, &kse); + if (ret != 0) return ret; - /* Set extension to be in response. */ - extension = TLSX_Find(*extensions, TLSX_KEY_SHARE); extension->resp = 1; #else @@ -9114,7 +9120,7 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, int ret = INCOMPLETE_DATA; #ifdef WOLFSSL_ASYNC_CRYPT /* in async case make sure key generation is finalized */ - serverKSE = (KeyShareEntry*)extension->data; + KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data; if (serverKSE && serverKSE->lastRet == WC_PENDING_E) { if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) *searched = 1; @@ -9168,14 +9174,30 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) KeyShareEntry* serverKSE; KeyShareEntry* list = NULL; - if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END || - clientKSE == NULL) + if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END) return BAD_FUNC_ARG; extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension == NULL) return BAD_STATE_E; + if (clientKSE == NULL) { +#ifdef WOLFSSL_ASYNC_CRYPT + /* Not necessarily an error. The key may have already been setup. */ + if (extension != NULL && extension->resp == 1) { + serverKSE = (KeyShareEntry*)extension->data; + if (serverKSE != NULL) { + /* in async case make sure key generation is finalized */ + if (serverKSE->lastRet == WC_PENDING_E) + return TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE); + else if (serverKSE->lastRet == 0) + return 0; + } + } +#endif + return BAD_FUNC_ARG; + } + /* Generate a new key pair except in the case of OQS KEM because we * are going to encapsulate and that does not require us to generate a * key pair. @@ -9230,7 +9252,7 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) extension->data = (void *)serverKSE; extension->resp = 1; - return 0; + return ret; } /* Ensure there is a key pair that can be used for key exchange. diff --git a/src/tls13.c b/src/tls13.c index 44b0ec687..78da84a58 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -6581,6 +6581,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.sendVerify = SEND_CERT; #if defined(WOLFSSL_SEND_HRR_COOKIE) + ssl->options.cookieGood = 0; if (ssl->options.sendCookie && (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE #ifdef WOLFSSL_DTLS13 @@ -6599,22 +6600,17 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); if (ret != 0) goto exit_dch; - ssl->options.serverState = SERVER_HELLO_COMPLETE; + /* Don't change state here as we may want to enter + * DoTls13ClientHello again. */ + ssl->options.cookieGood = 1; } else { -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls) - ssl->options.serverState = NULL_STATE; - else -#endif - ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); } } - else -#ifdef WOLFSSL_DTLS13 - if (!ssl->options.dtls) -#endif - ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); + else { + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); + } } #endif @@ -6659,12 +6655,14 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if ((ret = ALPN_Select(ssl)) != 0) goto exit_dch; #endif - /* Advance state and proceed */ - ssl->options.asyncState = TLS_ASYNC_BUILD; } /* case TLS_ASYNC_BEGIN */ FALL_THROUGH; case TLS_ASYNC_BUILD: + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + FALL_THROUGH; + case TLS_ASYNC_DO: { #ifndef NO_CERTS @@ -6673,7 +6671,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_ASYNC_CRYPT if (ret != WC_PENDING_E) #endif - WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + WOLFSSL_MSG("Unsupported cipher suite, ClientHello 1.3"); goto exit_dch; } } @@ -6695,10 +6693,31 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* Advance state and proceed */ - ssl->options.asyncState = TLS_ASYNC_FINALIZE; + ssl->options.asyncState = TLS_ASYNC_VERIFY; } /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */ FALL_THROUGH; + case TLS_ASYNC_VERIFY: + { +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SUPPORTED_CURVES) + /* Check if the KeyShare calculations from the previous state are complete. + * wolfSSL_AsyncPop advances ssl->options.asyncState so we may end up here + * with a pending calculation. */ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL && extension->resp == 1) { + KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data; + if (serverKSE != NULL && serverKSE->lastRet == WC_PENDING_E) { + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + if (ret != 0) + goto exit_dch; + } + } +#endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } + FALL_THROUGH; + case TLS_ASYNC_FINALIZE: { *inOutIdx = args->idx; @@ -6742,6 +6761,19 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = INPUT_CASE_ERROR; } /* switch (ssl->options.asyncState) */ +#if defined(WOLFSSL_SEND_HRR_COOKIE) + if (ret == 0 && ssl->options.sendCookie && ssl->options.cookieGood && + (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE +#ifdef WOLFSSL_DTLS13 + /* DTLS cookie exchange should be done in stateless code in + * DoClientHelloStateless. If we verified the cookie then + * always advance the state. */ + || ssl->options.dtls +#endif + )) + ssl->options.serverState = SERVER_HELLO_COMPLETE; +#endif + #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie && ssl->options.serverState <= SERVER_HELLO_RETRY_REQUEST_COMPLETE) { diff --git a/tests/api.c b/tests/api.c index 5f02f9f61..80e731d8e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -59356,6 +59356,12 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl) sslCopy.keys.dtls_peer_handshake_number = 0; XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history)); sslCopy.hsHashes = NULL; +#ifdef WOLFSSL_ASYNC_IO +#ifdef WOLFSSL_ASYNC_CRYPT + sslCopy.asyncDev = NULL; +#endif + sslCopy.async = NULL; +#endif AssertIntEQ(wc_HashInit(&hash, hashType), 0); AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)&sslCopy, sizeof(sslCopy)), 0); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 3b0bc62c8..9708d17d7 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3084,6 +3084,7 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions); +WOLFSSL_LOCAL int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse); WOLFSSL_LOCAL int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, KeyShareEntry** kse, byte* searched); WOLFSSL_LOCAL int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE); @@ -4389,10 +4390,13 @@ typedef struct Options { word16 tls13MiddleBoxCompat:1; /* TLSv1.3 middlebox compatibility */ #endif #ifdef WOLFSSL_DTLS_CID - byte useDtlsCID:1; + word16 useDtlsCID:1; #endif /* WOLFSSL_DTLS_CID */ #if defined(HAVE_ECH) - byte useEch:1; + word16 useEch:1; +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + word16 cookieGood:1; #endif /* need full byte values for this section */ From 4c7aa5c8ddab784c6747eeef5fba83f6ad757e6a Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 9 Mar 2023 19:00:25 +0100 Subject: [PATCH 29/29] Address code review --- src/dtls.c | 42 +++++++++++------------------------------- src/internal.c | 3 ++- src/keys.c | 6 ++++-- src/tls.c | 44 +++++++++++++++++++++++++++++++++----------- wolfssl/internal.h | 5 +++-- 5 files changed, 53 insertions(+), 47 deletions(-) diff --git a/src/dtls.c b/src/dtls.c index fda5a8957..513b6991e 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -296,7 +296,7 @@ static int ParseClientHello(const byte* input, word32 helloSz, WolfSSL_CH* ch) #if (defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) && defined(HAVE_SESSION_TICKET)) \ || defined(WOLFSSL_DTLS13) -static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType, +static int FindExtByType(WolfSSL_ConstVector* ret, word16 extType, WolfSSL_ConstVector exts, int* tlsxFound) { word32 len, idx = 0; @@ -335,7 +335,7 @@ static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts, int ret = 0; int tlsxFound; - ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts, + ret = FindExtByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts, &tlsxFound); if (ret != 0) return ret; @@ -437,7 +437,7 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, ProtocolVersion pv = ssl->version; int tlsxFound; - ret = TlsxFindByType(&tlsxSupportedVersions, TLSX_SUPPORTED_VERSIONS, + ret = FindExtByType(&tlsxSupportedVersions, TLSX_SUPPORTED_VERSIONS, ch->extension, &tlsxFound); if (ret != 0) return ret; @@ -456,26 +456,6 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl, return 0; } - -static int CopySupportedGroup(TLSX* src, TLSX** dst, void* heap) -{ - TLSX* extension; - int ret; - - extension = TLSX_Find(src, TLSX_SUPPORTED_GROUPS); - if (extension != NULL) { - SupportedCurve* curve; - curve = (SupportedCurve*)extension->data; - for (curve = (SupportedCurve*)extension->data; curve != NULL; - curve = curve->next) { - ret = TLSX_UseSupportedCurve(dst, curve->name, heap); - if (ret != WOLFSSL_SUCCESS) - return MEMORY_E; - } - } - - return 0; -} #endif #if defined(WOLFSSL_DTLS13) && \ @@ -619,12 +599,12 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* Set that this is a response extension */ parsedExts->resp = 1; - ret = CopySupportedGroup(ssl->extensions, &parsedExts, ssl->heap); + ret = TLSX_SupportedCurve_Copy(ssl->extensions, &parsedExts, ssl->heap); if (ret != 0) goto dtls13_cleanup; /* Signature algs */ - ret = TlsxFindByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, + ret = FindExtByType(&tlsx, TLSX_SIGNATURE_ALGORITHMS, ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; @@ -643,7 +623,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) } /* Supported groups */ - ret = TlsxFindByType(&tlsx, TLSX_SUPPORTED_GROUPS, + ret = FindExtByType(&tlsx, TLSX_SUPPORTED_GROUPS, ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; @@ -656,7 +636,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) } /* Key share */ - ret = TlsxFindByType(&tlsx, TLSX_KEY_SHARE, + ret = FindExtByType(&tlsx, TLSX_KEY_SHARE, ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; @@ -670,7 +650,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Pre-shared key */ - ret = TlsxFindByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension, &tlsxFound); + ret = FindExtByType(&tlsx, TLSX_PRE_SHARED_KEY, ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; if (tlsxFound) { @@ -686,7 +666,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) /* Revert to full handshake if PSK parsing failed */ if (pskInfo.isValid) { - ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, + ret = FindExtByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES, ch->extension, &tlsxFound); if (ret != 0) goto dtls13_cleanup; @@ -760,7 +740,7 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) } /* This is required to correctly generate the hash */ - ret = SetCipherSpecs_ex(WOLFSSL_SERVER_END, cs.cipherSuite0, + ret = GetCipherSpec(WOLFSSL_SERVER_END, cs.cipherSuite0, cs.cipherSuite, &specs, NULL); if (ret != 0) goto dtls13_cleanup; @@ -879,7 +859,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, return ret; if (isTls13) { int tlsxFound; - ret = TlsxFindByType(&ch.cookieExt, TLSX_COOKIE, ch.extension, + ret = FindExtByType(&ch.cookieExt, TLSX_COOKIE, ch.extension, &tlsxFound); if (ret != 0) return ret; diff --git a/src/internal.c b/src/internal.c index aad2ae532..731495eb3 100644 --- a/src/internal.c +++ b/src/internal.c @@ -32660,7 +32660,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES) - if (!TLSX_ValidateSupportedCurves(ssl, first, second, cs)) { + if (!TLSX_ValidateSupportedCurves(ssl, first, second, + &cs->ecdhCurveOID)) { WOLFSSL_MSG("Don't have matching curves"); return 0; } diff --git a/src/keys.c b/src/keys.c index e4a579602..8f960ba0e 100644 --- a/src/keys.c +++ b/src/keys.c @@ -44,7 +44,7 @@ int SetCipherSpecs(WOLFSSL* ssl) { - int ret = SetCipherSpecs_ex(ssl->options.side, ssl->options.cipherSuite0, + int ret = GetCipherSpec(ssl->options.side, ssl->options.cipherSuite0, ssl->options.cipherSuite, &ssl->specs, &ssl->options); if (ret == 0) { @@ -97,6 +97,8 @@ int SetCipherSpecs(WOLFSSL* ssl) } /** + * Populate specs with the specification of the chosen ciphersuite. If opts is + * not NULL then the appropriate options will also be set. * * @param side [in] WOLFSSL_SERVER_END or WOLFSSL_CLIENT_END * @param cipherSuite0 [in] @@ -105,7 +107,7 @@ int SetCipherSpecs(WOLFSSL* ssl) * @param opts [in/out] Options can be NULL * @return */ -int SetCipherSpecs_ex(word16 side, byte cipherSuite0, byte cipherSuite, +int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, CipherSpecs* specs, Options* opts) { word16 havePSK = 0; diff --git a/src/tls.c b/src/tls.c index 541f60900..0c0a52528 100644 --- a/src/tls.c +++ b/src/tls.c @@ -4544,7 +4544,7 @@ static int TLSX_PointFormat_Parse(WOLFSSL* ssl, const byte* input, #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, - CipherSuite* cs) { + word32* ecdhCurveOID) { TLSX* extension = NULL; SupportedCurve* curve = NULL; word32 oid = 0; @@ -4856,29 +4856,30 @@ int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, } } + *ecdhCurveOID = ssl->ecdhCurveOID; /* Choose the default if it is at the required strength. */ #ifdef HAVE_ECC - if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) + if (*ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) #else - if (ssl->ecdhCurveOID == 0) + if (*ecdhCurveOID == 0) #endif { key = 1; - cs->ecdhCurveOID = defOid; + *ecdhCurveOID = defOid; } /* Choose any curve at the required strength. */ - if (ssl->ecdhCurveOID == 0) { + if (*ecdhCurveOID == 0) { key = 1; - cs->ecdhCurveOID = currOid; + *ecdhCurveOID = currOid; } /* Choose the default if it is at the next highest strength. */ - if (cs->ecdhCurveOID == 0 && defSz == nextSz) - cs->ecdhCurveOID = defOid; + if (*ecdhCurveOID == 0 && defSz == nextSz) + *ecdhCurveOID = defOid; /* Choose any curve at the next highest strength. */ - if (cs->ecdhCurveOID == 0) - cs->ecdhCurveOID = nextOid; + if (*ecdhCurveOID == 0) + *ecdhCurveOID = nextOid; /* No curve and ephemeral ECC suite requires a matching curve. */ - if (cs->ecdhCurveOID == 0 && ephmSuite) + if (*ecdhCurveOID == 0 && ephmSuite) key = 0; return key; @@ -4887,6 +4888,27 @@ int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, #endif /* NO_WOLFSSL_SERVER */ + +int TLSX_SupportedCurve_Copy(TLSX* src, TLSX** dst, void* heap) +{ + TLSX* extension; + int ret; + + extension = TLSX_Find(src, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) { + SupportedCurve* curve; + curve = (SupportedCurve*)extension->data; + for (curve = (SupportedCurve*)extension->data; curve != NULL; + curve = curve->next) { + ret = TLSX_UseSupportedCurve(dst, curve->name, heap); + if (ret != WOLFSSL_SUCCESS) + return MEMORY_E; + } + } + + return 0; +} + int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) { TLSX* extension = NULL; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9708d17d7..575c3e917 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2899,6 +2899,7 @@ typedef struct PointFormat { struct PointFormat* next; /* List Behavior */ } PointFormat; +WOLFSSL_LOCAL int TLSX_SupportedCurve_Copy(TLSX* src, TLSX** dst, void* heap); WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap); @@ -2907,7 +2908,7 @@ WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point, #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, - byte second, CipherSuite* cs); + byte second, word32* ecdhCurveOID); WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl); #endif @@ -5690,7 +5691,7 @@ WOLFSSL_LOCAL int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr); WOLFSSL_LOCAL const char* AlertTypeToString(int type); WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL* ssl); -WOLFSSL_LOCAL int SetCipherSpecs_ex(word16 side, byte cipherSuite0, +WOLFSSL_LOCAL int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, CipherSpecs* specs, Options* opts); WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL* ssl);