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