forked from wolfSSL/wolfssl
Merge branch 'dtls-cookie'
This commit is contained in:
152
src/internal.c
152
src/internal.c
@@ -112,6 +112,9 @@ static int BuildMessage(WOLFSSL* ssl, byte* output, int outSz,
|
||||
#ifdef HAVE_STUNNEL
|
||||
static int SNI_Callback(WOLFSSL* ssl);
|
||||
#endif
|
||||
#ifdef WOLFSSL_DTLS
|
||||
static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte);
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -479,7 +482,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
|
||||
if (method->version.major == DTLS_MAJOR) {
|
||||
ctx->CBIORecv = EmbedReceiveFrom;
|
||||
ctx->CBIOSend = EmbedSendTo;
|
||||
ctx->CBIOCookie = EmbedGenerateCookie;
|
||||
}
|
||||
#endif
|
||||
#endif /* WOLFSSL_USER_IO */
|
||||
@@ -1907,6 +1909,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("DTLS Cookie Secret error");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
|
||||
|
||||
#ifdef HAVE_SECRET_CALLBACK
|
||||
ssl->sessionSecretCb = NULL;
|
||||
ssl->sessionSecretCtx = NULL;
|
||||
@@ -5112,7 +5124,9 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
||||
|
||||
/* above checks handshake state */
|
||||
/* hello_request not hashed */
|
||||
if (type != hello_request) {
|
||||
/* 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 && !(ssl->options.dtls && type == client_hello)) {
|
||||
ret = HashInput(ssl, input + *inOutIdx, size);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
@@ -14262,6 +14276,13 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
Suites clSuites;
|
||||
word32 i = *inOutIdx;
|
||||
word32 begin = i;
|
||||
#ifdef WOLFSSL_DTLS
|
||||
Hmac cookieHmac;
|
||||
byte peerCookie[MAX_COOKIE_LEN];
|
||||
byte peerCookieSz;
|
||||
byte cookieType;
|
||||
byte cookieSz;
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
#ifdef WOLFSSL_CALLBACKS
|
||||
if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
|
||||
@@ -14275,6 +14296,33 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
/* protocol version */
|
||||
XMEMCPY(&pv, input + i, OPAQUE16_LEN);
|
||||
ssl->chVersion = pv; /* store */
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
int ret;
|
||||
#if defined(NO_SHA) && defined(NO_SHA256)
|
||||
#error "DTLS needs either SHA or SHA-256"
|
||||
#endif /* NO_SHA && NO_SHA256 */
|
||||
|
||||
#ifndef NO_SHA
|
||||
cookieType = SHA;
|
||||
cookieSz = SHA_DIGEST_SIZE;
|
||||
#endif /* NO_SHA */
|
||||
#ifndef NO_SHA256
|
||||
cookieType = SHA256;
|
||||
cookieSz = SHA256_DIGEST_SIZE;
|
||||
#endif /* NO_SHA256 */
|
||||
ret = wc_HmacSetKey(&cookieHmac, cookieType,
|
||||
ssl->buffers.dtlsCookieSecret.buffer,
|
||||
ssl->buffers.dtlsCookieSecret.length);
|
||||
if (ret != 0) return ret;
|
||||
ret = wc_HmacUpdate(&cookieHmac,
|
||||
ssl->buffers.dtlsCtx.peer.sa,
|
||||
ssl->buffers.dtlsCtx.peer.sz);
|
||||
if (ret != 0) return ret;
|
||||
ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
i += OPAQUE16_LEN;
|
||||
|
||||
if ((!ssl->options.dtls && ssl->version.minor > pv.minor) ||
|
||||
@@ -14325,6 +14373,12 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
|
||||
/* random */
|
||||
XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN);
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
int ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
i += RAN_LEN;
|
||||
|
||||
#ifdef SHOW_SECRETS
|
||||
@@ -14345,6 +14399,12 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
return BUFFER_ERROR;
|
||||
|
||||
XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN);
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
int ret = wc_HmacUpdate(&cookieHmac, input + i - 1, ID_LEN + 1);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
ssl->arrays->sessionIDSz = ID_LEN;
|
||||
i += ID_LEN;
|
||||
ssl->options.resuming = 1; /* client wants to resume */
|
||||
@@ -14362,30 +14422,18 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
if ((i - begin) + OPAQUE8_LEN > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
b = input[i++];
|
||||
peerCookieSz = input[i++];
|
||||
|
||||
if (b) {
|
||||
byte cookie[MAX_COOKIE_LEN];
|
||||
|
||||
if (b > MAX_COOKIE_LEN)
|
||||
if (peerCookieSz) {
|
||||
if (peerCookieSz > MAX_COOKIE_LEN)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if ((i - begin) + b > helloSz)
|
||||
if ((i - begin) + peerCookieSz > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (ssl->ctx->CBIOCookie == NULL) {
|
||||
WOLFSSL_MSG("Your Cookie callback is null, please set");
|
||||
return COOKIE_ERROR;
|
||||
}
|
||||
XMEMCPY(peerCookie, input + i, peerCookieSz);
|
||||
|
||||
if ((ssl->ctx->CBIOCookie(ssl, cookie, COOKIE_SZ,
|
||||
ssl->IOCB_CookieCtx) != COOKIE_SZ)
|
||||
|| (b != COOKIE_SZ)
|
||||
|| (XMEMCMP(cookie, input + i, b) != 0)) {
|
||||
return COOKIE_ERROR;
|
||||
}
|
||||
|
||||
i += b;
|
||||
i += peerCookieSz;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -14405,6 +14453,14 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
return BUFFER_ERROR;
|
||||
|
||||
XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
int ret = wc_HmacUpdate(&cookieHmac,
|
||||
input + i - OPAQUE16_LEN,
|
||||
clSuites.suiteSz + OPAQUE16_LEN);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
i += clSuites.suiteSz;
|
||||
clSuites.hashSigAlgoSz = 0;
|
||||
|
||||
@@ -14414,6 +14470,43 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
if ((i - begin) + b > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
byte newCookie[MAX_COOKIE_LEN];
|
||||
int ret;
|
||||
|
||||
ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1);
|
||||
if (ret != 0) return ret;
|
||||
ret = wc_HmacFinal(&cookieHmac, newCookie);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
/* If a cookie callback is set, call it to overwrite the cookie.
|
||||
* This should be deprecated. The code now calculates the cookie
|
||||
* using an HMAC as expected. */
|
||||
if (ssl->ctx->CBIOCookie != NULL &&
|
||||
ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz,
|
||||
ssl->IOCB_CookieCtx) != cookieSz) {
|
||||
return COOKIE_ERROR;
|
||||
}
|
||||
|
||||
/* Check the cookie, see if we progress the state machine. */
|
||||
if (peerCookieSz != cookieSz ||
|
||||
XMEMCMP(peerCookie, newCookie, cookieSz) != 0) {
|
||||
|
||||
/* Send newCookie to client in a HelloVerifyRequest message
|
||||
* and let the state machine alone. */
|
||||
ssl->msgsReceived.got_client_hello = 0;
|
||||
*inOutIdx += helloSz;
|
||||
return SendHelloVerifyRequest(ssl, newCookie, cookieSz);
|
||||
}
|
||||
|
||||
/* This was skipped in the DTLS case so we could handle the hello
|
||||
* verify request. */
|
||||
ret = HashInput(ssl, input + *inOutIdx, helloSz);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
if (ssl->options.usingCompression) {
|
||||
int match = 0;
|
||||
|
||||
@@ -14519,8 +14612,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
ssl->options.haveSessionId = 1;
|
||||
|
||||
/* ProcessOld uses same resume code */
|
||||
if (ssl->options.resuming && (!ssl->options.dtls ||
|
||||
ssl->options.acceptState == HELLO_VERIFY_SENT)) { /* let's try */
|
||||
if (ssl->options.resuming) {
|
||||
int ret = -1;
|
||||
WOLFSSL_SESSION* session = GetSession(ssl,
|
||||
ssl->arrays->masterSecret);
|
||||
@@ -15002,10 +15094,10 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
int SendHelloVerifyRequest(WOLFSSL* ssl)
|
||||
static int SendHelloVerifyRequest(WOLFSSL* ssl,
|
||||
const byte* cookie, byte cookieSz)
|
||||
{
|
||||
byte* output;
|
||||
byte cookieSz = COOKIE_SZ;
|
||||
int length = VERSION_SZ + ENUM_LEN + cookieSz;
|
||||
int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
|
||||
int sendSz = length + idx;
|
||||
@@ -15030,17 +15122,10 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
output[idx++] = DTLS_MINOR;
|
||||
|
||||
output[idx++] = cookieSz;
|
||||
if (ssl->ctx->CBIOCookie == NULL) {
|
||||
WOLFSSL_MSG("Your Cookie callback is null, please set");
|
||||
if (cookie == NULL || cookieSz == 0)
|
||||
return COOKIE_ERROR;
|
||||
}
|
||||
if ((ret = ssl->ctx->CBIOCookie(ssl, output + idx, cookieSz,
|
||||
ssl->IOCB_CookieCtx)) < 0)
|
||||
return ret;
|
||||
|
||||
ret = HashOutput(ssl, output, sendSz, 0);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
XMEMCPY(output + idx, cookie, cookieSz);
|
||||
|
||||
#ifdef WOLFSSL_CALLBACKS
|
||||
if (ssl->hsInfoOn)
|
||||
@@ -15049,7 +15134,6 @@ int DoSessionTicket(WOLFSSL* ssl,
|
||||
AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
|
||||
sendSz, ssl->heap);
|
||||
#endif
|
||||
ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
|
||||
|
||||
ssl->buffers.outputBuffer.length += sendSz;
|
||||
|
||||
|
114
src/ssl.c
114
src/ssl.c
@@ -5465,6 +5465,64 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
|
||||
#endif /* LEANPSK */
|
||||
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
|
||||
/* Not an SSL function, return 0 for success, error code otherwise */
|
||||
/* Prereq: ssl's RNG needs to be initialized. */
|
||||
int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
|
||||
const byte* secret, word32 secretSz)
|
||||
{
|
||||
WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
|
||||
|
||||
if (ssl == NULL) {
|
||||
WOLFSSL_MSG("need a SSL object");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (secret != NULL && secretSz == 0) {
|
||||
WOLFSSL_MSG("can't have a new secret without a size");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* If secretSz is 0, use the default size. */
|
||||
if (secretSz == 0)
|
||||
secretSz = COOKIE_SECRET_SZ;
|
||||
|
||||
if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
|
||||
byte* newSecret;
|
||||
|
||||
if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
|
||||
XMEMSET(ssl->buffers.dtlsCookieSecret.buffer, 0,
|
||||
ssl->buffers.dtlsCookieSecret.length);
|
||||
XFREE(ssl->buffers.dtlsCookieSecret.buffer,
|
||||
ssl->heap, DYNAMIC_TYPE_NONE);
|
||||
}
|
||||
|
||||
newSecret = (byte*)XMALLOC(secretSz, ssl->heap, DYNAMIC_TYPE_NONE);
|
||||
if (newSecret == NULL) {
|
||||
ssl->buffers.dtlsCookieSecret.buffer = NULL;
|
||||
ssl->buffers.dtlsCookieSecret.length = 0;
|
||||
WOLFSSL_MSG("couldn't allocate new cookie secret");
|
||||
return MEMORY_ERROR;
|
||||
}
|
||||
ssl->buffers.dtlsCookieSecret.buffer = newSecret;
|
||||
ssl->buffers.dtlsCookieSecret.length = secretSz;
|
||||
}
|
||||
|
||||
/* If the supplied secret is NULL, randomly generate a new secret. */
|
||||
if (secret == NULL)
|
||||
wc_RNG_GenerateBlock(ssl->rng,
|
||||
ssl->buffers.dtlsCookieSecret.buffer, secretSz);
|
||||
else
|
||||
XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
|
||||
|
||||
|
||||
/* client only parts */
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
|
||||
@@ -5883,62 +5941,6 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
|
||||
WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
|
||||
|
||||
case ACCEPT_CLIENT_HELLO_DONE :
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls)
|
||||
if ( (ssl->error = SendHelloVerifyRequest(ssl)) != 0) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
ssl->options.acceptState = HELLO_VERIFY_SENT;
|
||||
WOLFSSL_MSG("accept state HELLO_VERIFY_SENT");
|
||||
|
||||
case HELLO_VERIFY_SENT:
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->options.dtls) {
|
||||
ssl->options.clientState = NULL_STATE; /* get again */
|
||||
/* reset messages received */
|
||||
XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
|
||||
/* re-init hashes, exclude first hello and verify request */
|
||||
#ifndef NO_OLD_TLS
|
||||
wc_InitMd5(&ssl->hsHashes->hashMd5);
|
||||
if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha))
|
||||
!= 0) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
if (IsAtLeastTLSv1_2(ssl)) {
|
||||
#ifndef NO_SHA256
|
||||
if ( (ssl->error = wc_InitSha256(
|
||||
&ssl->hsHashes->hashSha256)) != 0) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
if ( (ssl->error = wc_InitSha384(
|
||||
&ssl->hsHashes->hashSha384)) != 0) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA512
|
||||
if ( (ssl->error = wc_InitSha512(
|
||||
&ssl->hsHashes->hashSha512)) != 0) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
|
||||
if ( (ssl->error = ProcessReply(ssl)) < 0) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
|
||||
WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
|
||||
|
||||
|
@@ -842,6 +842,7 @@ enum Misc {
|
||||
RAN_LEN = 32, /* random length */
|
||||
SEED_LEN = RAN_LEN * 2, /* tls prf seed length */
|
||||
ID_LEN = 32, /* session id length */
|
||||
COOKIE_SECRET_SZ = 14, /* dtls cookie secret size */
|
||||
MAX_COOKIE_LEN = 32, /* max dtls cookie size */
|
||||
COOKIE_SZ = 20, /* use a 20 byte cookie */
|
||||
SUITE_LEN = 2, /* cipher suite sz length */
|
||||
@@ -1951,7 +1952,6 @@ enum ConnectState {
|
||||
enum AcceptState {
|
||||
ACCEPT_BEGIN = 0,
|
||||
ACCEPT_CLIENT_HELLO_DONE,
|
||||
HELLO_VERIFY_SENT,
|
||||
ACCEPT_FIRST_REPLY_DONE,
|
||||
SERVER_HELLO_SENT,
|
||||
CERT_SENT,
|
||||
@@ -1993,6 +1993,9 @@ typedef struct Buffers {
|
||||
#endif
|
||||
#ifdef WOLFSSL_DTLS
|
||||
WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
buffer dtlsCookieSecret; /* DTLS cookie secret */
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
#endif
|
||||
#ifdef HAVE_PK_CALLBACKS
|
||||
#ifdef HAVE_ECC
|
||||
@@ -2603,9 +2606,6 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
WOLFSSL_LOCAL int SendServerHello(WOLFSSL*);
|
||||
WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*);
|
||||
#ifdef WOLFSSL_DTLS
|
||||
WOLFSSL_LOCAL int SendHelloVerifyRequest(WOLFSSL*);
|
||||
#endif
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
|
@@ -1041,6 +1041,9 @@ typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz,
|
||||
WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie);
|
||||
WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx);
|
||||
WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl);
|
||||
WOLFSSL_API int wolfSSL_DTLS_SetCookieSecret(WOLFSSL*,
|
||||
const unsigned char*,
|
||||
unsigned int);
|
||||
|
||||
|
||||
/* I/O Callback default errors */
|
||||
|
Reference in New Issue
Block a user