mirror of https://github.com/wolfSSL/wolfssl
Merge branch 'tickets'
This commit is contained in:
commit
ebf73fab5d
|
@ -64,6 +64,16 @@
|
|||
int myHsDoneCb(WOLFSSL* ssl, void* user_ctx);
|
||||
#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)
|
||||
{
|
||||
|
@ -415,6 +425,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
|||
if (ctx == NULL)
|
||||
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 (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
|
||||
err_sys("server can't set cipher list 1");
|
||||
|
@ -648,6 +665,11 @@ while (1) { /* allow resume option */
|
|||
fdCloseSession(Task_self());
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
|
||||
defined(HAVE_POLY1305)
|
||||
TicketCleanup();
|
||||
#endif
|
||||
|
||||
#ifndef CYASSL_TIRTOS
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -732,3 +754,89 @@ while (1) { /* allow resume option */
|
|||
}
|
||||
#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
|
||||
|
||||
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
|
||||
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4909,6 +4913,10 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
if (ssl->keys.encryptionOn) {
|
||||
*inOutIdx += ssl->keys.padSz;
|
||||
}
|
||||
if (ssl->options.resuming) {
|
||||
WOLFSSL_MSG("Not resuming as thought");
|
||||
ssl->options.resuming = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case finished:
|
||||
|
@ -8007,6 +8015,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
|||
case SOCKET_PEER_CLOSED_E:
|
||||
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 :
|
||||
return "unknown error number";
|
||||
}
|
||||
|
@ -9323,8 +9337,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
ret = ret ||
|
||||
(!ssl->expect_session_ticket && ssl->session.ticketLen > 0);
|
||||
/* server may send blank ticket which may not be expected to indicate
|
||||
* exisiting one ok but will also be sending a new one */
|
||||
ret = ret || (ssl->session.ticketLen > 0);
|
||||
#endif
|
||||
|
||||
ret = ret ||
|
||||
|
@ -11339,6 +11354,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
||||
int sendSz;
|
||||
int ret;
|
||||
byte sessIdSz = ID_LEN;
|
||||
|
||||
length = VERSION_SZ + RAN_LEN
|
||||
+ ID_LEN + ENUM_LEN
|
||||
|
@ -11347,6 +11363,14 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
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
|
||||
|
||||
/* check for avalaible size */
|
||||
|
@ -11392,17 +11416,19 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
}
|
||||
#endif
|
||||
/* then session id */
|
||||
output[idx++] = ID_LEN;
|
||||
output[idx++] = sessIdSz;
|
||||
if (sessIdSz) {
|
||||
|
||||
if (!ssl->options.resuming) {
|
||||
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->sessionID, ID_LEN);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (!ssl->options.resuming) {
|
||||
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->sessionID,
|
||||
sessIdSz);
|
||||
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 */
|
||||
output[idx++] = ssl->options.cipherSuite0;
|
||||
output[idx++] = ssl->options.cipherSuite;
|
||||
|
@ -13069,6 +13095,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
/* session id */
|
||||
if (sessionSz) {
|
||||
XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz);
|
||||
ssl->arrays->sessionIDSz = (byte)sessionSz;
|
||||
idx += sessionSz;
|
||||
ssl->options.resuming = 1;
|
||||
}
|
||||
|
@ -13090,7 +13117,14 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
/* DoClientHello uses same resume code */
|
||||
if (ssl->options.resuming) { /* let's try */
|
||||
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) {
|
||||
WOLFSSL_MSG("Session lookup for resume failed");
|
||||
ssl->options.resuming = 0;
|
||||
|
@ -13217,6 +13251,7 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
return BUFFER_ERROR;
|
||||
|
||||
XMEMCPY(ssl->arrays->sessionID, input + i, ID_LEN);
|
||||
ssl->arrays->sessionIDSz = ID_LEN;
|
||||
i += ID_LEN;
|
||||
ssl->options.resuming = 1; /* client wants to resume */
|
||||
WOLFSSL_MSG("Client wants to resume session");
|
||||
|
@ -13379,7 +13414,13 @@ int DoSessionTicket(WOLFSSL* ssl,
|
|||
if (ssl->options.resuming && (!ssl->options.dtls ||
|
||||
ssl->options.acceptState == HELLO_VERIFY_SENT)) { /* let's try */
|
||||
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) {
|
||||
WOLFSSL_MSG("Session lookup for resume failed");
|
||||
|
@ -13655,6 +13696,171 @@ int DoSessionTicket(WOLFSSL* 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
|
||||
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 */
|
||||
|
||||
/* 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 */
|
||||
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
|
||||
int wolfSSL_UseSessionTicket(WOLFSSL* ssl)
|
||||
|
@ -905,7 +920,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz)
|
|||
|
||||
if (bufSz > 0)
|
||||
XMEMCPY(ssl->session.ticket, buf, bufSz);
|
||||
ssl->session.ticketLen = bufSz;
|
||||
ssl->session.ticketLen = (word16)bufSz;
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
@ -5562,6 +5577,18 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
|
|||
WOLFSSL_MSG("accept state 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) {
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return SSL_FATAL_ERROR;
|
||||
|
@ -5808,6 +5835,11 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
|
|||
if (ssl->options.haveSessionId == 0)
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (ssl->arrays)
|
||||
id = ssl->arrays->sessionID;
|
||||
else
|
||||
|
@ -5896,6 +5928,11 @@ int AddSession(WOLFSSL* ssl)
|
|||
if (ssl->options.haveSessionId == 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;
|
||||
if (error != 0) {
|
||||
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)
|
||||
{
|
||||
return isRequest && ticket ? ticket->size : 0;
|
||||
(void)isRequest;
|
||||
return ticket ? ticket->size : 0;
|
||||
}
|
||||
|
||||
static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
|
||||
int isRequest)
|
||||
{
|
||||
int offset = 0; /* empty ticket */
|
||||
|
||||
word16 offset = 0; /* empty ticket */
|
||||
|
||||
if (isRequest && ticket) {
|
||||
XMEMCPY(output + offset, ticket->data, 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,
|
||||
byte isRequest)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!isRequest) {
|
||||
/* client side */
|
||||
if (length != 0)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
|
||||
ssl->expect_session_ticket = 1;
|
||||
}
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
else {
|
||||
/* TODO server side */
|
||||
(void)input;
|
||||
}
|
||||
/* server side */
|
||||
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,
|
||||
|
|
|
@ -129,6 +129,9 @@ enum wolfSSL_ErrorCodes {
|
|||
SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */
|
||||
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 !!!!! */
|
||||
|
||||
/* begin negotiation parameter errors */
|
||||
|
|
|
@ -764,6 +764,7 @@ enum Misc {
|
|||
VERIFY_HEADER = 2, /* always use 2 bytes */
|
||||
EXT_ID_SZ = 2, /* always use 2 bytes */
|
||||
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! */
|
||||
RAN_LEN = 32, /* random length */
|
||||
|
@ -910,6 +911,10 @@ enum Misc {
|
|||
#define SESSION_TICKET_LEN 256
|
||||
#endif
|
||||
|
||||
#ifndef SESSION_TICKET_HINT_DEFAULT
|
||||
#define SESSION_TICKET_HINT_DEFAULT 300
|
||||
#endif
|
||||
|
||||
|
||||
/* don't use extra 3/4k stack space unless need to */
|
||||
#ifdef HAVE_NTRU
|
||||
|
@ -1535,6 +1540,10 @@ struct WOLFSSL_CTX {
|
|||
#endif
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
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
|
||||
#ifdef ATOMIC_USER
|
||||
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */
|
||||
|
@ -1797,6 +1806,7 @@ enum AcceptState {
|
|||
CERT_REQ_SENT,
|
||||
SERVER_HELLO_DONE,
|
||||
ACCEPT_SECOND_REPLY_DONE,
|
||||
TICKET_SENT,
|
||||
CHANGE_CIPHER_SENT,
|
||||
ACCEPT_FINISHED_DONE,
|
||||
ACCEPT_THIRD_REPLY_DONE
|
||||
|
@ -1889,7 +1899,11 @@ typedef struct Options {
|
|||
#endif
|
||||
#ifdef HAVE_ANON
|
||||
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 */
|
||||
byte processReply; /* nonblocking resume */
|
||||
|
@ -2353,6 +2367,8 @@ static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
|
|||
|
||||
/* internal functions */
|
||||
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 SendCertificate(WOLFSSL*);
|
||||
WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*);
|
||||
|
|
|
@ -1359,8 +1359,8 @@ WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl);
|
|||
|
||||
/* 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_CTX_UseSessionTicket(WOLFSSL_CTX* ctx);
|
||||
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*);
|
||||
WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*,
|
||||
CallbackSessionTicket, void*);
|
||||
#endif /* NO_WOLFSSL_CLIENT */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
|
||||
#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_START_MON 0x02 /* start monitoring flag */
|
||||
|
|
Loading…
Reference in New Issue