Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8933,6 +8933,45 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
const byte* secret,
word32 secretSz);

/*!
\brief This function sets a secondary DTLS 1.2 cookie secret used only when
verifying a received HelloVerifyRequest cookie, and only if the primary
secret (set with wolfSSL_DTLS_SetCookieSecret()) fails to verify it. This
lets an application rotate the cookie secret on a stateless server without
rejecting clients whose cookie was issued under the previous secret: install
the new secret as the primary and the previous secret here for an overlap
window. The secondary secret is never used to issue cookies. It is the
DTLS 1.2 counterpart of wolfSSL_set_hrr_cookie_secret_secondary().

\return 0 returned if the function executed without an error.
\return BAD_FUNC_ARG returned if ssl is NULL.
\return MEMORY_ERROR returned if there was a problem allocating
memory for the secondary cookie secret.

\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param secret a constant byte pointer representing the secret buffer.
Passing NULL (or a secretSz of 0) clears any previously set secondary secret.
\param secretSz the size of the buffer.

_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
const byte* oldSecret;
word32 oldSecretSz; // size of oldSecret
if(wolfSSL_DTLS_SetCookieSecretSecondary(ssl, oldSecret, oldSecretSz) != 0){
// Code block for failure to set secondary DTLS cookie secret
} else {
// Success! Secondary cookie secret is set.
}
\endcode

\sa wolfSSL_DTLS_SetCookieSecret
*/
int wolfSSL_DTLS_SetCookieSecretSecondary(WOLFSSL* ssl,
const byte* secret,
word32 secretSz);

/*!
\brief This function retrieves the random number.

Expand Down Expand Up @@ -13995,6 +14034,51 @@ int wolfSSL_connect(WOLFSSL* ssl);
int wolfSSL_send_hrr_cookie(WOLFSSL* ssl,
const unsigned char* secret, unsigned int secretSz);

/*!
\ingroup Setup

\brief This function sets a secondary HelloRetryRequest cookie secret on a
DTLS 1.3 server. It is used only when verifying a received cookie, and only
if the primary secret (set with wolfSSL_send_hrr_cookie()) fails to verify
it. This lets an application rotate the cookie secret on a stateless DTLS
1.3 server without rejecting clients whose cookie was issued under the
previous secret: install the new secret as the primary and the previous
secret here for an overlap window. The secondary secret is never used to
issue cookies. This API is DTLS only; TLS 1.3 over a reliable transport
does not verify cookies statelessly across the HelloRetryRequest exchange.

\param [in,out] ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param [in] secret a pointer to a buffer holding the secondary secret.
Passing NULL (or a secretSz of 0) clears any previously set secondary secret.
\param [in] secretSz Size of the secret in bytes.

\return BAD_FUNC_ARG if ssl is NULL, not using TLS v1.3, or not using DTLS.
\return SIDE_ERROR if called with a client.
\return WOLFSSL_SUCCESS if successful.
\return MEMORY_ERROR if allocating dynamic memory for storing secret failed.

_Example_
\code
int ret;
WOLFSSL* ssl;
char newSecret[32];
char oldSecret[32];
...
// rotate: new secret becomes primary, previous secret stays valid
wolfSSL_send_hrr_cookie(ssl, newSecret, sizeof(newSecret));
ret = wolfSSL_set_hrr_cookie_secret_secondary(ssl, oldSecret,
sizeof(oldSecret));
if (ret != WOLFSSL_SUCCESS) {
// failed to set the secondary cookie secret
}
\endcode

\sa wolfSSL_send_hrr_cookie
\sa wolfSSL_disable_hrr_cookie
*/
int wolfSSL_set_hrr_cookie_secret_secondary(WOLFSSL* ssl,
const unsigned char* secret, unsigned int secretSz);

/*!

\ingroup Setup
Expand Down
32 changes: 24 additions & 8 deletions src/dtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,12 @@ static word32 ReadVector16(const byte* input, WolfSSL_ConstVector* v)
}

static int CreateDtls12Cookie(const WOLFSSL* ssl, const WolfSSL_CH* ch,
byte* cookie)
const byte* secret, word32 secretSz, byte* cookie)
{
int ret;
WC_DECLARE_VAR(cookieHmac, Hmac, 1, ssl->heap);

if (ssl->buffers.dtlsCookieSecret.buffer == NULL ||
ssl->buffers.dtlsCookieSecret.length == 0) {
if (secret == NULL || secretSz == 0) {
WOLFSSL_MSG("Missing DTLS 1.2 cookie secret");
return COOKIE_ERROR;
}
Expand All @@ -225,9 +224,7 @@ static int CreateDtls12Cookie(const WOLFSSL* ssl, const WolfSSL_CH* ch,

ret = wc_HmacInit(cookieHmac, ssl->heap, ssl->devId);
if (ret == 0) {
ret = wc_HmacSetKey(cookieHmac, DTLS_COOKIE_TYPE,
ssl->buffers.dtlsCookieSecret.buffer,
ssl->buffers.dtlsCookieSecret.length);
ret = wc_HmacSetKey(cookieHmac, DTLS_COOKIE_TYPE, secret, secretSz);
if (ret == 0) {
/* peerLock not necessary. Still in handshake phase. */
ret = wc_HmacUpdate(cookieHmac,
Expand Down Expand Up @@ -288,13 +285,30 @@ static int CheckDtlsCookie(const WOLFSSL* ssl, WolfSSL_CH* ch,
if (ch->cookie.size != DTLS_COOKIE_SZ)
return 0;
if (!ch->dtls12cookieSet) {
ret = CreateDtls12Cookie(ssl, ch, ch->dtls12cookie);
ret = CreateDtls12Cookie(ssl, ch,
ssl->buffers.dtlsCookieSecret.buffer,
ssl->buffers.dtlsCookieSecret.length, ch->dtls12cookie);
if (ret != 0)
return ret;
ch->dtls12cookieSet = 1;
}
*cookieGood = ConstantCompare(ch->cookie.elements, ch->dtls12cookie,
DTLS_COOKIE_SZ) == 0;
/* If the primary secret didn't match, try the secondary (verify-only)
* secret. This lets a stateless server keep accepting cookies issued
* under the secret it held before an application-driven rotation. */
if (!*cookieGood &&
ssl->buffers.dtlsCookieSecretSecondary.buffer != NULL &&
ssl->buffers.dtlsCookieSecretSecondary.length > 0) {
byte altCookie[DTLS_COOKIE_SZ];
ret = CreateDtls12Cookie(ssl, ch,
ssl->buffers.dtlsCookieSecretSecondary.buffer,
ssl->buffers.dtlsCookieSecretSecondary.length, altCookie);
if (ret != 0)
return ret;
*cookieGood = ConstantCompare(ch->cookie.elements, altCookie,
DTLS_COOKIE_SZ) == 0;
}
}
return ret;
}
Expand Down Expand Up @@ -907,7 +921,9 @@ static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13)
{
#if !defined(WOLFSSL_NO_TLS12)
if (!ch->dtls12cookieSet) {
ret = CreateDtls12Cookie(ssl, ch, ch->dtls12cookie);
ret = CreateDtls12Cookie(ssl, ch,
ssl->buffers.dtlsCookieSecret.buffer,
ssl->buffers.dtlsCookieSecret.length, ch->dtls12cookie);
if (ret != 0)
return ret;
ch->dtls12cookieSet = 1;
Expand Down
20 changes: 20 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -8959,6 +8959,16 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
}
XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
ssl->buffers.tls13CookieSecret.buffer = NULL;
ssl->buffers.tls13CookieSecret.length = 0;
if (ssl->buffers.tls13CookieSecretSecondary.buffer != NULL) {
ForceZero(ssl->buffers.tls13CookieSecretSecondary.buffer,
ssl->buffers.tls13CookieSecretSecondary.length);
}
XFREE(ssl->buffers.tls13CookieSecretSecondary.buffer, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
ssl->buffers.tls13CookieSecretSecondary.buffer = NULL;
ssl->buffers.tls13CookieSecretSecondary.length = 0;
#endif
#ifdef WOLFSSL_DTLS
DtlsMsgPoolReset(ssl);
Expand All @@ -8984,6 +8994,16 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
}
XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
ssl->buffers.dtlsCookieSecret.buffer = NULL;
ssl->buffers.dtlsCookieSecret.length = 0;
if (ssl->buffers.dtlsCookieSecretSecondary.buffer != NULL) {
ForceZero(ssl->buffers.dtlsCookieSecretSecondary.buffer,
ssl->buffers.dtlsCookieSecretSecondary.length);
}
XFREE(ssl->buffers.dtlsCookieSecretSecondary.buffer, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
ssl->buffers.dtlsCookieSecretSecondary.buffer = NULL;
ssl->buffers.dtlsCookieSecretSecondary.length = 0;
#endif

#ifdef WOLFSSL_DTLS13
Expand Down
67 changes: 67 additions & 0 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -6389,6 +6389,73 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
return ret;
}

/* Set a secondary DTLS 1.2 cookie secret used only when verifying a received
* HelloVerifyRequest cookie, and only if the primary secret (set by
* wolfSSL_DTLS_SetCookieSecret()) fails to verify it.
*
* This supports an application-driven cookie-secret rotation on a stateless
* server: after rotating the primary secret, install the previous secret here
* so that cookies already issued under it are still accepted for an overlap
* window. It is never used to issue cookies.
*
* This is the DTLS 1.2 counterpart of wolfSSL_set_hrr_cookie_secret_secondary()
* (which covers the DTLS 1.3 HelloRetryRequest cookie); the two cookie
* mechanisms keep separate secrets, so a server that handles both versions sets
* both secondary secrets.
*
* ssl SSL/TLS object.
* secret Secondary secret to verify cookies against. A value of NULL (or a
* secretSz of 0) clears any previously set secondary secret.
* secretSz Size of secret data in bytes.
* returns BAD_FUNC_ARG when ssl is NULL, 0 on success and otherwise failure.
*/
int wolfSSL_DTLS_SetCookieSecretSecondary(WOLFSSL* ssl,
const byte* secret, word32 secretSz)
{
WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecretSecondary");

if (ssl == NULL) {
WOLFSSL_MSG("need a SSL object");
return BAD_FUNC_ARG;
}

/* Clear any existing secondary secret. */
if (ssl->buffers.dtlsCookieSecretSecondary.buffer != NULL) {
ForceZero(ssl->buffers.dtlsCookieSecretSecondary.buffer,
ssl->buffers.dtlsCookieSecretSecondary.length);
XFREE(ssl->buffers.dtlsCookieSecretSecondary.buffer,
ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
ssl->buffers.dtlsCookieSecretSecondary.buffer = NULL;
ssl->buffers.dtlsCookieSecretSecondary.length = 0;
}

/* A NULL/empty secret just clears the secondary secret. */
if (secret == NULL || secretSz == 0) {
WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecretSecondary", 0);
return 0;
}

{
byte* newSecret = (byte*)XMALLOC(secretSz, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
if (newSecret == NULL) {
WOLFSSL_MSG("couldn't allocate secondary cookie secret");
return MEMORY_ERROR;
}
XMEMCPY(newSecret, secret, secretSz);
ssl->buffers.dtlsCookieSecretSecondary.buffer = newSecret;
ssl->buffers.dtlsCookieSecretSecondary.length = secretSz;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecretSecondary secret",
ssl->buffers.dtlsCookieSecretSecondary.buffer,
ssl->buffers.dtlsCookieSecretSecondary.length);
#endif
}

WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecretSecondary", 0);
return 0;
}

#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */


Expand Down
Loading
Loading