diff --git a/src/internal.c b/src/internal.c index 02bbfd6b6..366b442c7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1677,8 +1677,10 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side) defined(OPENSSL_EXTRA) static int ctxInitTicket(WOLFSSL_CTX* ctx) { - WC_RNG rng; int ret = 0; +#if (defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) \ + || (!defined(NO_AES) && defined(HAVE_AESGCM) && defined(HAVE_AESGCM)) + WC_RNG rng; ret = wc_InitRng(&rng); if (ret != 0) @@ -1689,59 +1691,102 @@ static int ctxInitTicket(WOLFSSL_CTX* ctx) 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); +#else + (void)ctx; +#endif 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) { + 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* userCtx) { + int ret; + word16 sLen = XHTONS(inLen); + byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2]; + byte* tmp = aad; + WOLFSSL_ENTER("myTicketEncCbCompat"); - if (ssl == NULL || name == NULL || iv == NULL || ectx == NULL - || hctx == NULL) - return TICKET_KEY_CB_RET_FAILURE; + if (ssl == NULL || key_name == NULL || iv == NULL || mac == NULL + || ticket == NULL || outLen == NULL) + return WOLFSSL_TICKET_RET_FATAL; + + (void)userCtx; 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; - } + XMEMCPY(key_name, ssl->ctx->ticketCompatName, WOLFSSL_TICKET_NAME_SZ); + ret = wc_RNG_GenerateBlock(ssl->rng, iv, WOLFSSL_TICKET_IV_SZ); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; } 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; + /* see if we know this key */ + if (XMEMCMP(key_name, ssl->ctx->ticketCompatName, + WOLFSSL_TICKET_NAME_SZ) != 0){ + WOLFSSL_MSG("client presented unknown ticket key name"); + return WOLFSSL_TICKET_RET_FATAL; } } - return TICKET_KEY_CB_RET_OK; + + /* 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); + + /* encrypt */ + if (enc) { +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + ret = wc_ChaCha20Poly1305_Encrypt(ssl->ctx->ticketCompatKey, iv, + aad, sizeof(aad), ticket, inLen, ticket, mac); +#elif !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_256) + Aes aes; + ret = wc_AesInit(&aes, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, ssl->ctx->ticketCompatKey, AES_256_KEY_SIZE); + if (ret == 0) + ret = wc_AesGcmEncrypt(&aes, ticket, ticket, inLen, iv, + WOLFSSL_TICKET_IV_SZ, mac, AES_BLOCK_SIZE, + aad, sizeof(aad)); + wc_AesFree(&aes); + } +#else + WOLFSSL_MSG("Neither chacha20-poly1305 or aes-gcm available for " + "session ticket generation"); + return WOLFSSL_TICKET_RET_FATAL; +#endif + } + /* decrypt */ + else { +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + ret = wc_ChaCha20Poly1305_Decrypt(ssl->ctx->ticketCompatKey, iv, + aad, sizeof(aad), ticket, inLen, mac, ticket); +#elif !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_256) + Aes aes; + ret = wc_AesInit(&aes, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, ssl->ctx->ticketCompatKey, AES_256_KEY_SIZE); + if (ret == 0) + ret = wc_AesGcmDecrypt(&aes, ticket, ticket, inLen, iv, + WOLFSSL_TICKET_IV_SZ, mac, AES_BLOCK_SIZE, + aad, sizeof(aad)); + wc_AesFree(&aes); + } +#else + WOLFSSL_MSG("Neither chacha20-poly1305 or aes-gcm available for " + "session ticket decryption"); + return WOLFSSL_TICKET_RET_FATAL; +#endif + } + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + *outLen = inLen; /* no padding in this mode */ + + return WOLFSSL_TICKET_RET_OK; } #endif /* HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER && OPENSSL_EXTRA */ @@ -1900,14 +1945,17 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #ifdef OPENSSL_EXTRA if (ret == 0) ret = ctxInitTicket(ctx); +#if (defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) \ + || (!defined(NO_AES) && defined(HAVE_AESGCM) && defined(HAVE_AESGCM)) /* 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_CTX_set_TicketEncCb(ctx, myTicketEncCbCompat) != WOLFSSL_SUCCESS) ret = SESSION_SECRET_CB_E; #endif #endif +#endif #ifdef HAVE_WOLF_EVENT if (ret == 0) @@ -2054,10 +2102,9 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) } #endif /* WOLFSSL_STATIC_MEMORY */ #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \ - defined(OPENSSL_EXTRA) + defined(OPENSSL_EXTRA) && ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) \ + || (!defined(NO_AES) && defined(HAVE_AESGCM) && defined(HAVE_AESGCM))) 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 38d086100..93b1f81eb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15708,7 +15708,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) defined(OPENSSL_EXTRA) if (ctx->mask & SSL_OP_NO_TICKET) { ctx->ticketEncCb = NULL; - ctx->ticketCompatCb = NULL; + ctx->ticketEncCtx = NULL; + XMEMSET(ctx->ticketCompatName, 0, WOLFSSL_TICKET_NAME_SZ); +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \ + defined(OPENSSL_EXTRA) && ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) \ + || (!defined(NO_AES) && defined(HAVE_AESGCM) && defined(HAVE_AESGCM))) + ForceZero(ctx->ticketCompatKey, sizeof(ctx->ticketCompatKey)); +#endif WOLFSSL_MSG("\tSSL_OP_NO_TICKET"); } #endif @@ -47618,7 +47624,12 @@ 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 /* Implementation of session ticket encryption/decryption using OpenSSL * callback to initialize the cipher and HMAC. @@ -47637,11 +47648,11 @@ int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) * WOLFSSL_TICKET_RET_FATAL on error. */ static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, - unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], - unsigned char iv[WOLFSSL_TICKET_IV_SZ], - unsigned char mac[WOLFSSL_TICKET_MAC_SZ], - int enc, unsigned char* encTicket, - int encTicketLen, int* encLen, void* ctx) + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) { byte digest[WC_MAX_DIGEST_SIZE]; WOLFSSL_EVP_CIPHER_CTX evpCtx; @@ -47655,18 +47666,19 @@ static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, WOLFSSL_ENTER("wolfSSL_TicketKeyCb"); - if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketCompatCb == NULL) { + if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketEncCtx == NULL) { WOLFSSL_MSG("Bad parameter"); return WOLFSSL_TICKET_RET_FATAL; } + /* Initialize the cipher and HMAC. */ wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); 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); + res = ((ticketCompatCb)ssl->ctx->ticketEncCtx)(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; @@ -47729,16 +47741,13 @@ end: * cb The OpenSSL session ticket callback. * returns WOLFSSL_SUCCESS to indicate success. */ -int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( - WOLFSSL *ssl, unsigned char *name, unsigned char *iv, - WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, ticketCompatCb cb) { - /* Store callback in a global. */ - ctx->ticketCompatCb = cb; /* Set the ticket encryption callback to be a wrapper around OpenSSL * callback. */ ctx->ticketEncCb = wolfSSL_TicketKeyCb; + ctx->ticketEncCtx = cb; return WOLFSSL_SUCCESS; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9b02f70ba..a2e6f2f96 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -59,6 +59,9 @@ #ifdef HAVE_POLY1305 #include #endif +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && defined(OPENSSL_EXTRA) + #include +#endif #ifdef HAVE_CAMELLIA #include #endif @@ -2932,6 +2935,7 @@ struct WOLFSSL_CTX { #endif #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 6b7085768..9f6be4e20 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3252,13 +3252,6 @@ 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], @@ -3993,9 +3986,9 @@ WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, const WOLFSSL_ASN1_INTEGER *a); #ifdef HAVE_SESSION_TICKET -WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( - WOLFSSL *ssl, unsigned char *name, unsigned char *iv, - WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +typedef int (*ticketCompatCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, ticketCompatCb); #endif #if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \