Compat layer session tickets

- OpenSSL uses an internal mechanism by default for session tickets. This is now implemented for OPENSSL_EXTRA in wolfSSL.
- Add testing of wolfSSL_CTX_set_tlsext_ticket_key_cb
This commit is contained in:
Juliusz Sosinowicz
2021-01-11 16:06:43 +01:00
parent 9a1e54cfd5
commit 26df833074
8 changed files with 201 additions and 25 deletions

View File

@ -169,8 +169,14 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
if (TicketInit() != 0)
err_sys("unable to setup Session Ticket Key context");
#ifdef OPENSSL_EXTRA
/* In OpenSSL compat case, the compat layer handles the session
* tickets internally by default */
#elif ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || \
defined(HAVE_AESGCM))
wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
#endif
#endif
#ifndef NO_FILESYSTEM
if (doPSK == 0) {

View File

@ -1804,8 +1804,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
if (TicketInit() != 0)
err_sys_ex(catastrophic, "unable to setup Session Ticket Key context");
#ifdef OPENSSL_EXTRA
/* In OpenSSL compat case, the compat layer handles the session
* tickets internally by default */
#elif ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || \
defined(HAVE_AESGCM))
wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
#endif
#endif
#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_STATIC_EPHEMERAL)
/* used for testing only to set a static/fixed ephemeral key

View File

@ -1673,6 +1673,78 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side)
}
#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \
defined(OPENSSL_EXTRA)
static int ctxInitTicket(WOLFSSL_CTX* ctx)
{
WC_RNG rng;
int ret = 0;
ret = wc_InitRng(&rng);
if (ret != 0)
return ret;
ret = wc_RNG_GenerateBlock(&rng,
ctx->ticketCompatName, sizeof(ctx->ticketCompatName));
if (ret == 0)
ret = wc_RNG_GenerateBlock(&rng,
ctx->ticketCompatKey, sizeof(ctx->ticketCompatKey));
if (ret == 0)
ret = wc_RNG_GenerateBlock(&rng,
ctx->ticketCompatHmacKey, sizeof(ctx->ticketCompatHmacKey));
if (ret == 0)
ret = wc_RNG_GenerateBlock(&rng,
ctx->ticketCompatIV, sizeof(ctx->ticketCompatIV));
wc_FreeRng(&rng);
return ret;
}
static WC_INLINE int myTicketEncCbCompat(WOLFSSL* ssl,
byte name[WOLFSSL_TICKET_NAME_SZ],
byte iv[WOLFSSL_TICKET_IV_SZ],
WOLFSSL_EVP_CIPHER_CTX *ectx,
WOLFSSL_HMAC_CTX *hctx, int enc) {
WOLFSSL_ENTER("myTicketEncCbCompat");
if (ssl == NULL || name == NULL || iv == NULL || ectx == NULL
|| hctx == NULL)
return TICKET_KEY_CB_RET_FAILURE;
if (enc) {
XMEMCPY(name, ssl->ctx->ticketCompatName, sizeof(ssl->ctx->ticketCompatName));
XMEMCPY(iv, ssl->ctx->ticketCompatIV, sizeof(ssl->ctx->ticketCompatIV));
}
else if (XMEMCMP(name, ssl->ctx->ticketCompatName,
sizeof(ssl->ctx->ticketCompatName)) != 0 ||
XMEMCMP(iv, ssl->ctx->ticketCompatIV,
sizeof(ssl->ctx->ticketCompatIV)) != 0) {
WOLFSSL_MSG("myTicketEncCbCompat: name or iv mismatch");
return TICKET_KEY_CB_RET_NOT_FOUND;
}
if (wolfSSL_HMAC_Init(hctx, ssl->ctx->ticketCompatHmacKey,
WOLFSSL_TICKET_NAME_SZ, wolfSSL_EVP_sha256()) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("wolfSSL_HMAC_Init error");
return TICKET_KEY_CB_RET_FAILURE;
}
if (enc) {
if (wolfSSL_EVP_EncryptInit(ectx, wolfSSL_EVP_aes_256_cbc(),
ssl->ctx->ticketCompatKey, iv) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("wolfSSL_EVP_EncryptInit error");
return TICKET_KEY_CB_RET_FAILURE;
}
}
else {
if (wolfSSL_EVP_DecryptInit(ectx, wolfSSL_EVP_aes_256_cbc(),
ssl->ctx->ticketCompatKey, iv) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("wolfSSL_EVP_DecryptInit error");
return TICKET_KEY_CB_RET_FAILURE;
}
}
return TICKET_KEY_CB_RET_OK;
}
#endif /* HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER && OPENSSL_EXTRA */
/* Initialize SSL context, return 0 on success */
int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
{
@ -1825,10 +1897,21 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
ctx->ticketEncCtx = (void*)&ctx->ticketKeyCtx;
#endif
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
#ifdef OPENSSL_EXTRA
if (ret == 0)
ret = ctxInitTicket(ctx);
/* No need for compat ticket init flag since below callback setter is
* only called when the above parameter generation has succeeded */
if (ret == 0 &&
wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbCompat)
!= WOLFSSL_SUCCESS)
ret = SESSION_SECRET_CB_E;
#endif
#endif
#ifdef HAVE_WOLF_EVENT
ret = wolfEventQueue_Init(&ctx->event_queue);
if (ret == 0)
ret = wolfEventQueue_Init(&ctx->event_queue);
#endif /* HAVE_WOLF_EVENT */
#ifdef WOLFSSL_EARLY_DATA
@ -1970,6 +2053,12 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
}
}
#endif /* WOLFSSL_STATIC_MEMORY */
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \
defined(OPENSSL_EXTRA)
ForceZero(ctx->ticketCompatKey, sizeof(ctx->ticketCompatKey));
ForceZero(ctx->ticketCompatHmacKey, sizeof(ctx->ticketCompatHmacKey));
ForceZero(ctx->ticketCompatIV, sizeof(ctx->ticketCompatIV));
#endif
}

View File

@ -15704,6 +15704,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ctx->mask = wolf_set_options(ctx->mask, opt);
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
if (ctx->mask & SSL_OP_NO_TICKET) {
ctx->ticketEncCb = NULL;
ctx->ticketCompatCb = NULL;
WOLFSSL_MSG("\tSSL_OP_NO_TICKET");
}
#endif
return ctx->mask;
}
@ -47561,16 +47569,7 @@ int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a)
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
/* Expected return values from implementations of OpenSSL ticket key callback.
*/
#define TICKET_KEY_CB_RET_FAILURE -1
#define TICKET_KEY_CB_RET_NOT_FOUND 0
#define TICKET_KEY_CB_RET_OK 1
#define TICKET_KEY_CB_RET_RENEW 2
/* The ticket key callback as used in OpenSSL is stored here. */
static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv,
WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL;
/* Implementation of session ticket encryption/decryption using OpenSSL
* callback to initialize the cipher and HMAC.
@ -47605,14 +47604,24 @@ static int wolfSSL_TicketKeyCb(WOLFSSL* ssl,
(void)ctx;
if (ticketKeyCb == NULL)
WOLFSSL_ENTER("wolfSSL_TicketKeyCb");
if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketCompatCb == NULL) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_TICKET_RET_FATAL;
}
wolfSSL_EVP_CIPHER_CTX_init(&evpCtx);
/* Initialize the cipher and HMAC. */
res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc);
if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW)
if (wolfSSL_HMAC_CTX_Init(&hmacCtx) != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init error");
return WOLFSSL_TICKET_RET_FATAL;
}
/* Initialize the cipher and HMAC. */
res = ssl->ctx->ticketCompatCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc);
if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) {
WOLFSSL_MSG("Ticket callback error");
return WOLFSSL_TICKET_RET_FATAL;
}
if (enc)
{
@ -47676,7 +47685,7 @@ int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)(
WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc))
{
/* Store callback in a global. */
ticketKeyCb = cb;
ctx->ticketCompatCb = cb;
/* Set the ticket encryption callback to be a wrapper around OpenSSL
* callback.
*/

View File

@ -2649,8 +2649,12 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
TicketInit();
#ifdef OPENSSL_EXTRA
wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL);
#else
wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
#endif
#endif
#if defined(USE_WINDOWS_API)
port = ((func_args*)args)->signal->port;

View File

@ -2931,6 +2931,7 @@ struct WOLFSSL_CTX {
TicketEncCbCtx ticketKeyCtx;
#endif
#endif
#endif
#ifdef HAVE_SUPPORTED_CURVES
byte userCurves; /* indicates user called wolfSSL_CTX_UseSupportedCurve */
#endif

View File

@ -3252,6 +3252,13 @@ enum TicketEncRet {
WOLFSSL_API int wolfSSL_CTX_NoTicketTLSv12(WOLFSSL_CTX* ctx);
WOLFSSL_API int wolfSSL_NoTicketTLSv12(WOLFSSL* ssl);
/* Expected return values from implementations of OpenSSL ticket key callback.
*/
#define TICKET_KEY_CB_RET_FAILURE -1
#define TICKET_KEY_CB_RET_NOT_FOUND 0
#define TICKET_KEY_CB_RET_OK 1
#define TICKET_KEY_CB_RET_RENEW 2
typedef int (*SessionTicketEncCb)(WOLFSSL*,
unsigned char key_name[WOLFSSL_TICKET_NAME_SZ],
unsigned char iv[WOLFSSL_TICKET_IV_SZ],

View File

@ -3930,10 +3930,71 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num)
}
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || \
defined(HAVE_AESGCM))
static THREAD_LS_T WC_RNG myKey_rng;
static WC_INLINE void TicketCleanup(void)
{
wc_FreeRng(&myKey_rng);
}
#ifdef OPENSSL_EXTRA
typedef struct key_ctx {
byte name[WOLFSSL_TICKET_NAME_SZ]; /* server name */
byte key[AES_256_KEY_SIZE]; /* cipher key */
byte hmacKey[WOLFSSL_TICKET_NAME_SZ]; /* hmac key */
byte iv[WOLFSSL_TICKET_IV_SZ]; /* cipher iv */
} key_ctx;
static THREAD_LS_T key_ctx myKey_ctx;
static WC_INLINE int TicketInit(void)
{
int ret = wc_InitRng(&myKey_rng);
if (ret != 0) return ret;
ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.name, sizeof(myKey_ctx.name));
if (ret != 0) return ret;
ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.key, sizeof(myKey_ctx.key));
if (ret != 0) return ret;
ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.hmacKey, sizeof(myKey_ctx.hmacKey));
if (ret != 0) return ret;
ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.iv,sizeof(myKey_ctx.iv));
if (ret != 0) return ret;
return 0;
}
static WC_INLINE int myTicketEncCbOpenSSL(WOLFSSL* ssl,
byte name[WOLFSSL_TICKET_NAME_SZ],
byte iv[WOLFSSL_TICKET_IV_SZ],
WOLFSSL_EVP_CIPHER_CTX *ectx,
WOLFSSL_HMAC_CTX *hctx, int enc) {
(void)ssl;
if (enc) {
XMEMCPY(name, myKey_ctx.name, sizeof(myKey_ctx.name));
XMEMCPY(iv, myKey_ctx.iv, sizeof(myKey_ctx.iv));
}
else if (XMEMCMP(name, myKey_ctx.name, sizeof(myKey_ctx.name)) != 0 ||
XMEMCMP(iv, myKey_ctx.iv, sizeof(myKey_ctx.iv)) != 0) {
return 0;
}
HMAC_Init_ex(hctx, myKey_ctx.hmacKey, WOLFSSL_TICKET_NAME_SZ, EVP_sha256(), NULL);
if (enc)
EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, myKey_ctx.key, iv);
else
EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, myKey_ctx.key, iv);
return 1;
}
#elif ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || \
defined(HAVE_AESGCM))
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
@ -3950,7 +4011,6 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num)
} key_ctx;
static THREAD_LS_T key_ctx myKey_ctx;
static THREAD_LS_T WC_RNG myKey_rng;
static WC_INLINE int TicketInit(void)
{
@ -3966,11 +4026,6 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num)
return 0;
}
static WC_INLINE void TicketCleanup(void)
{
wc_FreeRng(&myKey_rng);
}
static WC_INLINE int myTicketEncCb(WOLFSSL* ssl,
byte key_name[WOLFSSL_TICKET_NAME_SZ],
byte iv[WOLFSSL_TICKET_IV_SZ],
@ -4068,9 +4123,8 @@ static WC_INLINE const char* mymktemp(char *tempfn, int len, int num)
return WOLFSSL_TICKET_RET_OK;
}
#endif /* HAVE_SESSION_TICKET && ((HAVE_CHACHA && HAVE_POLY1305) || HAVE_AESGCM) */
#endif /* OPENSSL_EXTRA elif ((HAVE_CHACHA && HAVE_POLY1305) || HAVE_AESGCM) */
#endif /* HAVE_SESSION_TICKET */
static WC_INLINE word16 GetRandomPort(void)
{