diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 1ef3007f8..d864f8cb2 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -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) { diff --git a/examples/server/server.c b/examples/server/server.c index 05b6f2f54..2260fa46c 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -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 diff --git a/src/internal.c b/src/internal.c index 1b8eec9b9..02bbfd6b6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -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 } diff --git a/src/ssl.c b/src/ssl.c index ebccbeb7e..97a096458 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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. */ diff --git a/tests/api.c b/tests/api.c index cde3746e4..7224d3af4 100644 --- a/tests/api.c +++ b/tests/api.c @@ -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; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 2cbc325a0..9b02f70ba 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -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 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 9a5496918..6b7085768 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -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], diff --git a/wolfssl/test.h b/wolfssl/test.h index 5da853e60..6e0df1ceb 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -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 @@ -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) {