forked from wolfSSL/wolfssl
Merge branch 'tickets'
This commit is contained in:
@ -64,6 +64,16 @@
|
|||||||
int myHsDoneCb(WOLFSSL* ssl, void* user_ctx);
|
int myHsDoneCb(WOLFSSL* ssl, void* user_ctx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
|
||||||
|
defined(HAVE_POLY1305)
|
||||||
|
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
|
||||||
|
static int TicketInit(void);
|
||||||
|
static void TicketCleanup(void);
|
||||||
|
static int myTicketEncCb(WOLFSSL* ssl, byte key_name[16], byte iv[16],
|
||||||
|
byte mac[32], int enc, byte* ticket, int inLen,
|
||||||
|
int* outLen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void NonBlockingSSL_Accept(SSL* ssl)
|
static void NonBlockingSSL_Accept(SSL* ssl)
|
||||||
{
|
{
|
||||||
@ -415,6 +425,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
err_sys("unable to get ctx");
|
err_sys("unable to get ctx");
|
||||||
|
|
||||||
|
#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
|
||||||
|
defined(HAVE_POLY1305)
|
||||||
|
if (TicketInit() != 0)
|
||||||
|
err_sys("unable to setup Session Ticket Key context");
|
||||||
|
wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cipherList)
|
if (cipherList)
|
||||||
if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
|
if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
|
||||||
err_sys("server can't set cipher list 1");
|
err_sys("server can't set cipher list 1");
|
||||||
@ -648,6 +665,11 @@ while (1) { /* allow resume option */
|
|||||||
fdCloseSession(Task_self());
|
fdCloseSession(Task_self());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
|
||||||
|
defined(HAVE_POLY1305)
|
||||||
|
TicketCleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CYASSL_TIRTOS
|
#ifndef CYASSL_TIRTOS
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
@ -732,3 +754,89 @@ while (1) { /* allow resume option */
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
|
||||||
|
defined(HAVE_POLY1305)
|
||||||
|
typedef struct key_ctx {
|
||||||
|
byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */
|
||||||
|
byte key[16]; /* cipher key */
|
||||||
|
} key_ctx;
|
||||||
|
|
||||||
|
static key_ctx myKey_ctx;
|
||||||
|
static RNG rng;
|
||||||
|
|
||||||
|
static int TicketInit(void)
|
||||||
|
{
|
||||||
|
int ret = wc_InitRng(&rng);
|
||||||
|
if (ret != 0) return ret;
|
||||||
|
|
||||||
|
ret = wc_RNG_GenerateBlock(&rng, myKey_ctx.key, sizeof(myKey_ctx.key));
|
||||||
|
if (ret != 0) return ret;
|
||||||
|
|
||||||
|
ret = wc_RNG_GenerateBlock(&rng, myKey_ctx.name,sizeof(myKey_ctx.name));
|
||||||
|
if (ret != 0) return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TicketCleanup(void)
|
||||||
|
{
|
||||||
|
wc_FreeRng(&rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int myTicketEncCb(WOLFSSL* ssl,
|
||||||
|
byte key_name[WOLFSSL_TICKET_NAME_SZ],
|
||||||
|
byte iv[WOLFSSL_TICKET_IV_SZ],
|
||||||
|
byte mac[WOLFSSL_TICKET_MAC_SZ],
|
||||||
|
int enc, byte* ticket, int inLen, int* outLen)
|
||||||
|
{
|
||||||
|
(void)ssl;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
word16 sLen = htons(inLen);
|
||||||
|
byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2];
|
||||||
|
int aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2;
|
||||||
|
byte* tmp = aad;
|
||||||
|
|
||||||
|
if (enc) {
|
||||||
|
XMEMCPY(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ);
|
||||||
|
|
||||||
|
ret = wc_RNG_GenerateBlock(&rng, iv, WOLFSSL_TICKET_IV_SZ);
|
||||||
|
if (ret != 0) return WOLFSSL_TICKET_RET_REJECT;
|
||||||
|
|
||||||
|
/* build aad from key name, iv, and length */
|
||||||
|
XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ);
|
||||||
|
tmp += WOLFSSL_TICKET_NAME_SZ;
|
||||||
|
XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ);
|
||||||
|
tmp += WOLFSSL_TICKET_IV_SZ;
|
||||||
|
XMEMCPY(tmp, &sLen, 2);
|
||||||
|
|
||||||
|
ret = wc_ChaCha20Poly1305_Encrypt(myKey_ctx.key, iv,
|
||||||
|
aad, aadSz,
|
||||||
|
ticket, inLen,
|
||||||
|
ticket,
|
||||||
|
mac);
|
||||||
|
if (ret != 0) return WOLFSSL_TICKET_RET_REJECT;
|
||||||
|
*outLen = inLen; /* no padding in this mode */
|
||||||
|
} else {
|
||||||
|
/* decrypt */
|
||||||
|
/* build aad from key name, iv, and length */
|
||||||
|
XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ);
|
||||||
|
tmp += WOLFSSL_TICKET_NAME_SZ;
|
||||||
|
XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ);
|
||||||
|
tmp += WOLFSSL_TICKET_IV_SZ;
|
||||||
|
XMEMCPY(tmp, &sLen, 2);
|
||||||
|
|
||||||
|
ret = wc_ChaCha20Poly1305_Decrypt(myKey_ctx.key, iv,
|
||||||
|
aad, aadSz,
|
||||||
|
ticket, inLen,
|
||||||
|
mac,
|
||||||
|
ticket);
|
||||||
|
if (ret != 0) return WOLFSSL_TICKET_RET_REJECT;
|
||||||
|
*outLen = inLen; /* no padding in this mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
return WOLFSSL_TICKET_RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
230
src/internal.c
230
src/internal.c
@ -417,6 +417,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
|
||||||
|
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4909,6 +4913,10 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
if (ssl->keys.encryptionOn) {
|
if (ssl->keys.encryptionOn) {
|
||||||
*inOutIdx += ssl->keys.padSz;
|
*inOutIdx += ssl->keys.padSz;
|
||||||
}
|
}
|
||||||
|
if (ssl->options.resuming) {
|
||||||
|
WOLFSSL_MSG("Not resuming as thought");
|
||||||
|
ssl->options.resuming = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case finished:
|
case finished:
|
||||||
@ -8007,6 +8015,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
|||||||
case SOCKET_PEER_CLOSED_E:
|
case SOCKET_PEER_CLOSED_E:
|
||||||
return "Peer closed underlying transport Error";
|
return "Peer closed underlying transport Error";
|
||||||
|
|
||||||
|
case BAD_TICKET_KEY_CB_SZ:
|
||||||
|
return "Bad user session ticket key callback Size Error";
|
||||||
|
|
||||||
|
case BAD_TICKET_MSG_SZ:
|
||||||
|
return "Bad session ticket message Size Error";
|
||||||
|
|
||||||
default :
|
default :
|
||||||
return "unknown error number";
|
return "unknown error number";
|
||||||
}
|
}
|
||||||
@ -9323,8 +9337,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SESSION_TICKET
|
#ifdef HAVE_SESSION_TICKET
|
||||||
ret = ret ||
|
/* server may send blank ticket which may not be expected to indicate
|
||||||
(!ssl->expect_session_ticket && ssl->session.ticketLen > 0);
|
* exisiting one ok but will also be sending a new one */
|
||||||
|
ret = ret || (ssl->session.ticketLen > 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = ret ||
|
ret = ret ||
|
||||||
@ -11339,6 +11354,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
||||||
int sendSz;
|
int sendSz;
|
||||||
int ret;
|
int ret;
|
||||||
|
byte sessIdSz = ID_LEN;
|
||||||
|
|
||||||
length = VERSION_SZ + RAN_LEN
|
length = VERSION_SZ + RAN_LEN
|
||||||
+ ID_LEN + ENUM_LEN
|
+ ID_LEN + ENUM_LEN
|
||||||
@ -11347,6 +11363,14 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
|
|
||||||
#ifdef HAVE_TLS_EXTENSIONS
|
#ifdef HAVE_TLS_EXTENSIONS
|
||||||
length += TLSX_GetResponseSize(ssl);
|
length += TLSX_GetResponseSize(ssl);
|
||||||
|
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
if (ssl->options.useTicket && ssl->arrays->sessionIDSz == 0) {
|
||||||
|
/* no session id */
|
||||||
|
length -= ID_LEN;
|
||||||
|
sessIdSz = 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SESSION_TICKET */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check for avalaible size */
|
/* check for avalaible size */
|
||||||
@ -11392,17 +11416,19 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* then session id */
|
/* then session id */
|
||||||
output[idx++] = ID_LEN;
|
output[idx++] = sessIdSz;
|
||||||
|
if (sessIdSz) {
|
||||||
|
|
||||||
if (!ssl->options.resuming) {
|
if (!ssl->options.resuming) {
|
||||||
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->sessionID, ID_LEN);
|
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->sessionID,
|
||||||
if (ret != 0)
|
sessIdSz);
|
||||||
return ret;
|
if (ret != 0) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz);
|
||||||
|
idx += sessIdSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
XMEMCPY(output + idx, ssl->arrays->sessionID, ID_LEN);
|
|
||||||
idx += ID_LEN;
|
|
||||||
|
|
||||||
/* then cipher suite */
|
/* then cipher suite */
|
||||||
output[idx++] = ssl->options.cipherSuite0;
|
output[idx++] = ssl->options.cipherSuite0;
|
||||||
output[idx++] = ssl->options.cipherSuite;
|
output[idx++] = ssl->options.cipherSuite;
|
||||||
@ -13069,6 +13095,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
/* session id */
|
/* session id */
|
||||||
if (sessionSz) {
|
if (sessionSz) {
|
||||||
XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
|
XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
|
||||||
|
ssl->arrays->sessionIDSz = (byte)sessionSz;
|
||||||
idx += sessionSz;
|
idx += sessionSz;
|
||||||
ssl->options.resuming = 1;
|
ssl->options.resuming = 1;
|
||||||
}
|
}
|
||||||
@ -13090,7 +13117,14 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
/* DoClientHello uses same resume code */
|
/* DoClientHello uses same resume code */
|
||||||
if (ssl->options.resuming) { /* let's try */
|
if (ssl->options.resuming) { /* let's try */
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
WOLFSSL_SESSION* session = GetSession(ssl,ssl->arrays->masterSecret);
|
WOLFSSL_SESSION* session = GetSession(ssl,
|
||||||
|
ssl->arrays->masterSecret);
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
if (ssl->options.useTicket == 1) {
|
||||||
|
session = &ssl->session;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
WOLFSSL_MSG("Session lookup for resume failed");
|
WOLFSSL_MSG("Session lookup for resume failed");
|
||||||
ssl->options.resuming = 0;
|
ssl->options.resuming = 0;
|
||||||
@ -13217,6 +13251,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
|
|
||||||
XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN);
|
XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN);
|
||||||
|
ssl->arrays->sessionIDSz = ID_LEN;
|
||||||
i += ID_LEN;
|
i += ID_LEN;
|
||||||
ssl->options.resuming = 1; /* client wants to resume */
|
ssl->options.resuming = 1; /* client wants to resume */
|
||||||
WOLFSSL_MSG("Client wants to resume session");
|
WOLFSSL_MSG("Client wants to resume session");
|
||||||
@ -13379,7 +13414,13 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
if (ssl->options.resuming && (!ssl->options.dtls ||
|
if (ssl->options.resuming && (!ssl->options.dtls ||
|
||||||
ssl->options.acceptState == HELLO_VERIFY_SENT)) { /* let's try */
|
ssl->options.acceptState == HELLO_VERIFY_SENT)) { /* let's try */
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
WOLFSSL_SESSION* session = GetSession(ssl,ssl->arrays->masterSecret);
|
WOLFSSL_SESSION* session = GetSession(ssl,
|
||||||
|
ssl->arrays->masterSecret);
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
if (ssl->options.useTicket == 1) {
|
||||||
|
session = &ssl->session;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
WOLFSSL_MSG("Session lookup for resume failed");
|
WOLFSSL_MSG("Session lookup for resume failed");
|
||||||
@ -13655,6 +13696,171 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||||||
return SendBuffered(ssl);
|
return SendBuffered(ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
|
||||||
|
#define WOLFSSL_TICKET_FIXED_SZ (WOLFSSL_TICKET_NAME_SZ + \
|
||||||
|
WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ)
|
||||||
|
#define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ)
|
||||||
|
|
||||||
|
/* our ticket format */
|
||||||
|
typedef struct InternalTicket {
|
||||||
|
ProtocolVersion pv; /* version when ticket created */
|
||||||
|
byte suite[SUITE_LEN]; /* cipher suite when created */
|
||||||
|
byte msecret[SECRET_LEN]; /* master secret */
|
||||||
|
word32 timestamp; /* born on */
|
||||||
|
} InternalTicket;
|
||||||
|
|
||||||
|
/* fit within SESSION_TICKET_LEN */
|
||||||
|
typedef struct ExternalTicket {
|
||||||
|
byte key_name[WOLFSSL_TICKET_NAME_SZ]; /* key context name */
|
||||||
|
byte iv[WOLFSSL_TICKET_IV_SZ]; /* this ticket's iv */
|
||||||
|
byte enc_len[LENGTH_SZ]; /* encrypted length */
|
||||||
|
byte enc_ticket[WOLFSSL_TICKET_ENC_SZ]; /* encrypted internal ticket */
|
||||||
|
byte mac[WOLFSSL_TICKET_MAC_SZ]; /* total mac */
|
||||||
|
/* !! if add to structure, add to TICKET_FIXED_SZ !! */
|
||||||
|
} ExternalTicket;
|
||||||
|
|
||||||
|
/* create a new session ticket, 0 on success */
|
||||||
|
static int CreateTicket(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
InternalTicket it;
|
||||||
|
ExternalTicket* et = (ExternalTicket*)ssl->session.ticket;
|
||||||
|
int encLen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* build internal */
|
||||||
|
it.pv.major = ssl->version.major;
|
||||||
|
it.pv.minor = ssl->version.minor;
|
||||||
|
|
||||||
|
it.suite[0] = ssl->options.cipherSuite0;
|
||||||
|
it.suite[1] = ssl->options.cipherSuite;
|
||||||
|
|
||||||
|
XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
|
||||||
|
c32toa(LowResTimer(), (byte*)&it.timestamp);
|
||||||
|
|
||||||
|
/* build external */
|
||||||
|
XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
|
||||||
|
|
||||||
|
/* encrypt */
|
||||||
|
encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */
|
||||||
|
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1,
|
||||||
|
et->enc_ticket, sizeof(InternalTicket),
|
||||||
|
&encLen);
|
||||||
|
if (ret == WOLFSSL_TICKET_RET_OK) {
|
||||||
|
if (encLen < (int)sizeof(InternalTicket) ||
|
||||||
|
encLen > WOLFSSL_TICKET_ENC_SZ) {
|
||||||
|
WOLFSSL_MSG("Bad user ticket encrypt size");
|
||||||
|
return BAD_TICKET_KEY_CB_SZ;
|
||||||
|
}
|
||||||
|
c16toa((word16)encLen, et->enc_len);
|
||||||
|
ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ);
|
||||||
|
if (encLen < WOLFSSL_TICKET_ENC_SZ) {
|
||||||
|
/* move mac up since whole enc buffer not used */
|
||||||
|
XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse ticket sent by client */
|
||||||
|
int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
|
||||||
|
{
|
||||||
|
ExternalTicket* et;
|
||||||
|
InternalTicket* it;
|
||||||
|
int ret;
|
||||||
|
int outLen;
|
||||||
|
word16 inLen;
|
||||||
|
|
||||||
|
if (len > SESSION_TICKET_LEN ||
|
||||||
|
len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
|
||||||
|
return BAD_TICKET_MSG_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
et = (ExternalTicket*)input;
|
||||||
|
it = (InternalTicket*)et->enc_ticket;
|
||||||
|
|
||||||
|
/* decrypt */
|
||||||
|
ato16(et->enc_len, &inLen);
|
||||||
|
if (inLen > (word16)(len - WOLFSSL_TICKET_FIXED_SZ)) {
|
||||||
|
return BAD_TICKET_MSG_SZ;
|
||||||
|
}
|
||||||
|
outLen = inLen; /* may be reduced by user padding */
|
||||||
|
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
|
||||||
|
et->enc_ticket + inLen, 0,
|
||||||
|
et->enc_ticket, inLen, &outLen);
|
||||||
|
if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret;
|
||||||
|
if (outLen > inLen || outLen < (int)sizeof(InternalTicket)) {
|
||||||
|
WOLFSSL_MSG("Bad user ticket decrypt len");
|
||||||
|
return BAD_TICKET_KEY_CB_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get master secret */
|
||||||
|
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE)
|
||||||
|
XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* send Session Ticket */
|
||||||
|
int SendTicket(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
byte* output;
|
||||||
|
int ret;
|
||||||
|
int sendSz;
|
||||||
|
word32 length = SESSION_HINT_SZ + LENGTH_SZ;
|
||||||
|
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
if (ssl->options.dtls) {
|
||||||
|
length += DTLS_RECORD_EXTRA;
|
||||||
|
idx += DTLS_RECORD_EXTRA;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ssl->options.createTicket) {
|
||||||
|
ret = CreateTicket(ssl);
|
||||||
|
if (ret != 0) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
length += ssl->session.ticketLen;
|
||||||
|
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
|
||||||
|
|
||||||
|
/* check for available size */
|
||||||
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* get ouput buffer */
|
||||||
|
output = ssl->buffers.outputBuffer.buffer +
|
||||||
|
ssl->buffers.outputBuffer.length;
|
||||||
|
|
||||||
|
AddHeaders(output, length, session_ticket, ssl);
|
||||||
|
|
||||||
|
/* hint */
|
||||||
|
c32toa(ssl->ctx->ticketHint, output + idx);
|
||||||
|
idx += SESSION_HINT_SZ;
|
||||||
|
|
||||||
|
/* length */
|
||||||
|
c16toa(ssl->session.ticketLen, output + idx);
|
||||||
|
idx += LENGTH_SZ;
|
||||||
|
|
||||||
|
/* ticket */
|
||||||
|
XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen);
|
||||||
|
/* idx += ssl->session.ticketLen; */
|
||||||
|
|
||||||
|
ret = HashOutput(ssl, output, sendSz, 0);
|
||||||
|
if (ret != 0) return ret;
|
||||||
|
ssl->buffers.outputBuffer.length += sendSz;
|
||||||
|
|
||||||
|
return SendBuffered(ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SESSION_TICKET */
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
int SendHelloVerifyRequest(WOLFSSL* ssl)
|
int SendHelloVerifyRequest(WOLFSSL* ssl)
|
||||||
{
|
{
|
||||||
|
39
src/ssl.c
39
src/ssl.c
@ -865,6 +865,21 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl)
|
|||||||
|
|
||||||
#endif /* HAVE_SECURE_RENEGOTIATION */
|
#endif /* HAVE_SECURE_RENEGOTIATION */
|
||||||
|
|
||||||
|
/* Session Ticket */
|
||||||
|
#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET)
|
||||||
|
/* SSL_SUCCESS on ok */
|
||||||
|
int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb)
|
||||||
|
{
|
||||||
|
if (ctx == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
ctx->ticketEncCb = cb;
|
||||||
|
|
||||||
|
return SSL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */
|
||||||
|
|
||||||
/* Session Ticket */
|
/* Session Ticket */
|
||||||
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
|
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
|
||||||
int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
|
int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
|
||||||
@ -905,7 +920,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz)
|
|||||||
|
|
||||||
if (bufSz > 0)
|
if (bufSz > 0)
|
||||||
XMEMCPY(ssl->session.ticket, buf, bufSz);
|
XMEMCPY(ssl->session.ticket, buf, bufSz);
|
||||||
ssl->session.ticketLen = bufSz;
|
ssl->session.ticketLen = (word16)bufSz;
|
||||||
|
|
||||||
return SSL_SUCCESS;
|
return SSL_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -5562,6 +5577,18 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
|
|||||||
WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
|
WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
|
||||||
|
|
||||||
case ACCEPT_SECOND_REPLY_DONE :
|
case ACCEPT_SECOND_REPLY_DONE :
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
if (ssl->options.createTicket) {
|
||||||
|
if ( (ssl->error = SendTicket(ssl)) != 0) {
|
||||||
|
WOLFSSL_ERROR(ssl->error);
|
||||||
|
return SSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SESSION_TICKET */
|
||||||
|
ssl->options.acceptState = TICKET_SENT;
|
||||||
|
WOLFSSL_MSG("accept state TICKET_SENT");
|
||||||
|
|
||||||
|
case TICKET_SENT:
|
||||||
if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
|
if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
|
||||||
WOLFSSL_ERROR(ssl->error);
|
WOLFSSL_ERROR(ssl->error);
|
||||||
return SSL_FATAL_ERROR;
|
return SSL_FATAL_ERROR;
|
||||||
@ -5808,6 +5835,11 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
|
|||||||
if (ssl->options.haveSessionId == 0)
|
if (ssl->options.haveSessionId == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ssl->arrays)
|
if (ssl->arrays)
|
||||||
id = ssl->arrays->sessionID;
|
id = ssl->arrays->sessionID;
|
||||||
else
|
else
|
||||||
@ -5896,6 +5928,11 @@ int AddSession(WOLFSSL* ssl)
|
|||||||
if (ssl->options.haveSessionId == 0)
|
if (ssl->options.haveSessionId == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS;
|
row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS;
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
WOLFSSL_MSG("Hash session failed");
|
WOLFSSL_MSG("Hash session failed");
|
||||||
|
60
src/tls.c
60
src/tls.c
@ -1800,14 +1800,15 @@ static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl)
|
|||||||
|
|
||||||
static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
|
static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
|
||||||
{
|
{
|
||||||
return isRequest && ticket ? ticket->size : 0;
|
(void)isRequest;
|
||||||
|
return ticket ? ticket->size : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
|
static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
|
||||||
int isRequest)
|
int isRequest)
|
||||||
{
|
{
|
||||||
int offset = 0; /* empty ticket */
|
word16 offset = 0; /* empty ticket */
|
||||||
|
|
||||||
if (isRequest && ticket) {
|
if (isRequest && ticket) {
|
||||||
XMEMCPY(output + offset, ticket->data, ticket->size);
|
XMEMCPY(output + offset, ticket->data, ticket->size);
|
||||||
offset += ticket->size;
|
offset += ticket->size;
|
||||||
@ -1820,18 +1821,61 @@ static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
|
|||||||
static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length,
|
||||||
byte isRequest)
|
byte isRequest)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!isRequest) {
|
if (!isRequest) {
|
||||||
|
/* client side */
|
||||||
if (length != 0)
|
if (length != 0)
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
|
|
||||||
ssl->expect_session_ticket = 1;
|
ssl->expect_session_ticket = 1;
|
||||||
}
|
}
|
||||||
|
#ifndef NO_WOLFSSL_SERVER
|
||||||
else {
|
else {
|
||||||
/* TODO server side */
|
/* server side */
|
||||||
(void)input;
|
if (ssl->ctx->ticketEncCb == NULL) {
|
||||||
}
|
WOLFSSL_MSG("Client sent session ticket, server has no callback");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
if (length == 0) {
|
||||||
|
/* blank ticket */
|
||||||
|
ret = TLSX_UseSessionTicket(&ssl->extensions, NULL);
|
||||||
|
if (ret == SSL_SUCCESS) {
|
||||||
|
ret = 0;
|
||||||
|
TLSX_SetResponse(ssl, SESSION_TICKET); /* send blank ticket */
|
||||||
|
ssl->options.createTicket = 1; /* will send ticket msg */
|
||||||
|
ssl->options.useTicket = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* got actual ticket from client */
|
||||||
|
ret = DoClientTicket(ssl, input, length);
|
||||||
|
if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */
|
||||||
|
WOLFSSL_MSG("Using exisitng client ticket");
|
||||||
|
ssl->options.useTicket = 1;
|
||||||
|
ssl->options.resuming = 1;
|
||||||
|
} else if (ret == WOLFSSL_TICKET_RET_CREATE) {
|
||||||
|
WOLFSSL_MSG("Using existing client ticket, creating new one");
|
||||||
|
ret = TLSX_UseSessionTicket(&ssl->extensions, NULL);
|
||||||
|
if (ret == SSL_SUCCESS) {
|
||||||
|
ret = 0;
|
||||||
|
TLSX_SetResponse(ssl, SESSION_TICKET);
|
||||||
|
/* send blank ticket */
|
||||||
|
ssl->options.createTicket = 1; /* will send ticket msg */
|
||||||
|
ssl->options.useTicket = 1;
|
||||||
|
ssl->options.resuming = 1;
|
||||||
|
}
|
||||||
|
} else if (ret == WOLFSSL_TICKET_RET_REJECT) {
|
||||||
|
WOLFSSL_MSG("Process client ticket rejected, not using");
|
||||||
|
ret = 0; /* not fatal */
|
||||||
|
} else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) {
|
||||||
|
WOLFSSL_MSG("Process client ticket fatal error, not using");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* NO_WOLFSSL_SERVER */
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
|
WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
|
||||||
|
@ -129,6 +129,9 @@ enum wolfSSL_ErrorCodes {
|
|||||||
SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */
|
SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */
|
||||||
SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */
|
SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */
|
||||||
|
|
||||||
|
BAD_TICKET_KEY_CB_SZ = -398, /* Bad session ticket key cb size */
|
||||||
|
BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */
|
||||||
|
|
||||||
/* add strings to SetErrorString !!!!! */
|
/* add strings to SetErrorString !!!!! */
|
||||||
|
|
||||||
/* begin negotiation parameter errors */
|
/* begin negotiation parameter errors */
|
||||||
|
@ -764,6 +764,7 @@ enum Misc {
|
|||||||
VERIFY_HEADER = 2, /* always use 2 bytes */
|
VERIFY_HEADER = 2, /* always use 2 bytes */
|
||||||
EXT_ID_SZ = 2, /* always use 2 bytes */
|
EXT_ID_SZ = 2, /* always use 2 bytes */
|
||||||
MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */
|
MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */
|
||||||
|
SESSION_HINT_SZ = 4, /* session timeout hint */
|
||||||
|
|
||||||
MAX_SUITE_SZ = 200, /* 100 suites for now! */
|
MAX_SUITE_SZ = 200, /* 100 suites for now! */
|
||||||
RAN_LEN = 32, /* random length */
|
RAN_LEN = 32, /* random length */
|
||||||
@ -910,6 +911,10 @@ enum Misc {
|
|||||||
#define SESSION_TICKET_LEN 256
|
#define SESSION_TICKET_LEN 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SESSION_TICKET_HINT_DEFAULT
|
||||||
|
#define SESSION_TICKET_HINT_DEFAULT 300
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* don't use extra 3/4k stack space unless need to */
|
/* don't use extra 3/4k stack space unless need to */
|
||||||
#ifdef HAVE_NTRU
|
#ifdef HAVE_NTRU
|
||||||
@ -1535,6 +1540,10 @@ struct WOLFSSL_CTX {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_TLS_EXTENSIONS
|
#ifdef HAVE_TLS_EXTENSIONS
|
||||||
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
||||||
|
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SEVER)
|
||||||
|
SessionTicketEncCb ticketEncCb; /* enc/dec session ticket Cb */
|
||||||
|
int ticketHint; /* ticket hint in seconds */
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef ATOMIC_USER
|
#ifdef ATOMIC_USER
|
||||||
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */
|
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */
|
||||||
@ -1797,6 +1806,7 @@ enum AcceptState {
|
|||||||
CERT_REQ_SENT,
|
CERT_REQ_SENT,
|
||||||
SERVER_HELLO_DONE,
|
SERVER_HELLO_DONE,
|
||||||
ACCEPT_SECOND_REPLY_DONE,
|
ACCEPT_SECOND_REPLY_DONE,
|
||||||
|
TICKET_SENT,
|
||||||
CHANGE_CIPHER_SENT,
|
CHANGE_CIPHER_SENT,
|
||||||
ACCEPT_FINISHED_DONE,
|
ACCEPT_FINISHED_DONE,
|
||||||
ACCEPT_THIRD_REPLY_DONE
|
ACCEPT_THIRD_REPLY_DONE
|
||||||
@ -1889,7 +1899,11 @@ typedef struct Options {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ANON
|
#ifdef HAVE_ANON
|
||||||
word16 haveAnon:1; /* User wants to allow Anon suites */
|
word16 haveAnon:1; /* User wants to allow Anon suites */
|
||||||
#endif /* HAVE_ANON */
|
#endif
|
||||||
|
#ifdef HAVE_SESSION_TICKET
|
||||||
|
word16 createTicket:1; /* Server to create new Ticket */
|
||||||
|
word16 useTicket:1; /* Use Ticket not session cache */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* need full byte values for this section */
|
/* need full byte values for this section */
|
||||||
byte processReply; /* nonblocking resume */
|
byte processReply; /* nonblocking resume */
|
||||||
@ -2353,6 +2367,8 @@ static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
|
|||||||
|
|
||||||
/* internal functions */
|
/* internal functions */
|
||||||
WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*);
|
WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*);
|
||||||
|
WOLFSSL_LOCAL int SendTicket(WOLFSSL*);
|
||||||
|
WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32);
|
||||||
WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int);
|
WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int);
|
||||||
WOLFSSL_LOCAL int SendCertificate(WOLFSSL*);
|
WOLFSSL_LOCAL int SendCertificate(WOLFSSL*);
|
||||||
WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
|
WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
|
||||||
|
@ -1359,8 +1359,8 @@ WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl);
|
|||||||
|
|
||||||
/* Session Ticket */
|
/* Session Ticket */
|
||||||
#ifdef HAVE_SESSION_TICKET
|
#ifdef HAVE_SESSION_TICKET
|
||||||
#ifndef NO_WOLFSSL_CLIENT
|
|
||||||
|
|
||||||
|
#ifndef NO_WOLFSSL_CLIENT
|
||||||
WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl);
|
WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl);
|
||||||
WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx);
|
WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx);
|
||||||
WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*);
|
WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*);
|
||||||
@ -1368,9 +1368,32 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, unsigned char*, unsigned int
|
|||||||
typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*);
|
typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*);
|
||||||
WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*,
|
WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*,
|
||||||
CallbackSessionTicket, void*);
|
CallbackSessionTicket, void*);
|
||||||
|
#endif /* NO_WOLFSSL_CLIENT */
|
||||||
|
|
||||||
#endif
|
#ifndef NO_WOLFSSL_SERVER
|
||||||
#endif
|
|
||||||
|
#define WOLFSSL_TICKET_NAME_SZ 16
|
||||||
|
#define WOLFSSL_TICKET_IV_SZ 16
|
||||||
|
#define WOLFSSL_TICKET_MAC_SZ 32
|
||||||
|
|
||||||
|
enum TicketEncRet {
|
||||||
|
WOLFSSL_TICKET_RET_FATAL = -1, /* fatal error, don't use ticket */
|
||||||
|
WOLFSSL_TICKET_RET_OK = 0, /* ok, use ticket */
|
||||||
|
WOLFSSL_TICKET_RET_REJECT, /* don't use ticket, but not fatal */
|
||||||
|
WOLFSSL_TICKET_RET_CREATE /* existing ticket ok and create new one */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*SessionTicketEncCb)(WOLFSSL*,
|
||||||
|
unsigned char key_name[WOLFSSL_TICKET_NAME_SZ],
|
||||||
|
unsigned char iv[WOLFSSL_TICKET_IV_SZ],
|
||||||
|
unsigned char mac[WOLFSSL_TICKET_MAC_SZ],
|
||||||
|
int enc, unsigned char*, int, int*);
|
||||||
|
WOLFSSL_API int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx,
|
||||||
|
SessionTicketEncCb);
|
||||||
|
|
||||||
|
#endif /* NO_WOLFSSL_SERVER */
|
||||||
|
|
||||||
|
#endif /* HAVE_SESSION_TICKET */
|
||||||
|
|
||||||
#define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */
|
#define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */
|
||||||
#define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */
|
#define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */
|
||||||
|
Reference in New Issue
Block a user