Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default session ticket enc/dec: allow AES-CBC with HMAC #7703

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 123 additions & 6 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -37718,7 +37718,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
itHash = HashObject((byte*)it, sizeof(*it), &error);
if (error == 0) {
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac,
1, et->enc_ticket, sizeof(InternalTicket), &encLen,
1, et->enc_ticket, WOLFSSL_INTERNAL_TICKET_LEN, &encLen,
SSL_TICKET_CTX(ssl));
}
else {
Expand All @@ -37733,7 +37733,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
goto error;
}
if (encLen < (int)sizeof(InternalTicket) ||
if (encLen < (int)WOLFSSL_INTERNAL_TICKET_LEN ||
encLen > (int)WOLFSSL_TICKET_ENC_SZ) {
WOLFSSL_MSG("Bad user ticket encrypt size");
ret = BAD_TICKET_KEY_CB_SZ;
Expand Down Expand Up @@ -37809,7 +37809,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_ENTER("DoDecryptTicket");

if (len > SESSION_TICKET_LEN ||
len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
len < (word32)(WOLFSSL_INTERNAL_TICKET_LEN +
WOLFSSL_TICKET_FIXED_SZ)) {
WOLFSSL_ERROR_VERBOSE(BAD_TICKET_MSG_SZ);
return WOLFSSL_TICKET_RET_REJECT;
}
Expand Down Expand Up @@ -37857,7 +37858,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return WOLFSSL_TICKET_RET_REJECT;
}
}
if (outLen > (int)inLen || outLen < (int)sizeof(InternalTicket)) {
if (outLen > (int)inLen || outLen < (int)WOLFSSL_INTERNAL_TICKET_LEN) {
WOLFSSL_MSG("Bad user ticket decrypt len");
WOLFSSL_ERROR_VERBOSE(BAD_TICKET_KEY_CB_SZ);
return BAD_TICKET_KEY_CB_SZ;
Expand Down Expand Up @@ -38551,7 +38552,123 @@ static void TicketEncCbCtx_Free(TicketEncCbCtx* keyCtx)
wc_FreeRng(&keyCtx->rng);
}

#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
#ifdef WOLFSSL_TICKET_ENC_CBC_HMAC
/* Ticket encryption/decryption implementation.
*
* @param [in] key Key for encryption/decryption and HMAC.
* @param [in] keyLen Length of key in bytes.
* @param [in] iv IV/Nonce for encryption/decryption.
* @param [in] aad Additional authentication data.
* @param [in] aadSz Length of additional authentication data.
* @param [in] in Data to encrypt/decrypt.
* @param [in] inLen Length of encrypted data.
* @param [out] out Resulting data from encrypt/decrypt.
* @param [out] outLen Size of resulting data.
* @param [in] tag Authentication tag for encrypted data.
* @param [in] heap Dynamic memory allocation data hint.
* @param [in] enc 1 when encrypting, 0 when decrypting.
* @return 0 on success.
* @return Other value when encryption/decryption fails.
*/
static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
byte* in, int inLen, byte* out, int* outLen, byte* tag,
void* heap, int enc)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
Aes* aes;
Hmac* hmac;
#else
Aes aes[1];
Hmac hmac[1];
#endif

(void)heap;

#ifdef WOLFSSL_SMALL_STACK
aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_TMP_BUFFER);
if (aes == NULL)
return MEMORY_E;
hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_TMP_BUFFER);
if (hmac == NULL) {
XFREE(aes, heap, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif

XMEMSET(aes, 0, sizeof(Aes));
XMEMSET(hmac, 0, sizeof(Hmac));

ret = wc_HmacInit(hmac, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (ret == 0) {
ret = wc_HmacSetKey(hmac, WOLFSSL_TICKET_ENC_HMAC, key + keyLen -
WOLFSSL_TICKET_HMAC_KEY_SZ, WOLFSSL_TICKET_HMAC_KEY_SZ);
}
if (ret == 0) {
ret = wc_HmacUpdate(hmac, aad, aadSz);
}

if (ret == 0) {
if (enc) {
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret == 0) {
ret = wc_AesSetKey(aes, key,
keyLen - WOLFSSL_TICKET_HMAC_KEY_SZ, iv, AES_ENCRYPTION);
}
if (ret == 0) {
ret = wc_HmacUpdate(hmac, in, inLen);
}
if (ret == 0) {
ret = wc_AesCbcEncrypt(aes, in, out, inLen);
}
if (ret == 0) {
XMEMSET(tag, 0, WOLFSSL_TICKET_MAC_SZ);
ret = wc_HmacFinal(hmac, tag);
}
wc_AesFree(aes);
}
else {
unsigned char calcTag[WOLFSSL_TICKET_MAC_SZ];

ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret == 0) {
ret = wc_AesSetKey(aes, key,
keyLen - WOLFSSL_TICKET_HMAC_KEY_SZ, iv, AES_DECRYPTION);
}
if (ret == 0) {
ret = wc_AesCbcDecrypt(aes, in, out, inLen);
}
if (ret == 0) {
ret = wc_HmacUpdate(hmac, out, inLen);
}
if (ret == 0) {
XMEMSET(calcTag, 0, WOLFSSL_TICKET_MAC_SZ);
ret = wc_HmacFinal(hmac, calcTag);
}
if (ret == 0) {
int i;
calcTag[0] ^= tag[0];
for (i = 1; i < WOLFSSL_TICKET_MAC_SZ; i++) {
calcTag[0] |= calcTag[i] ^ tag[i];
}
/* Return a negative value when no match. */
ret = -calcTag[0];
}
wc_AesFree(aes);
}
}
wc_HmacFree(hmac);

#ifdef WOLFSSL_SMALL_STACK
XFREE(hmac, heap, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(aes, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif

*outLen = inLen;

return ret;
}
#elif defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
!defined(WOLFSSL_TICKET_ENC_AES128_GCM) && \
!defined(WOLFSSL_TICKET_ENC_AES256_GCM)
/* Ticket encryption/decryption implementation.
Expand Down Expand Up @@ -38846,7 +38963,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],

WOLFSSL_ENTER("DefTicketEncCb");

if ((!enc) && (inLen != sizeof(InternalTicket))) {
if ((!enc) && (inLen != WOLFSSL_INTERNAL_TICKET_LEN)) {
return BUFFER_E;
}

Expand Down
7 changes: 7 additions & 0 deletions wolfssl/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3328,6 +3328,13 @@ typedef struct InternalTicket {
#endif /* OPENSSL_EXTRA */
} InternalTicket;

#ifndef WOLFSSL_TICKET_ENC_CBC_HMAC
#define WOLFSSL_INTERNAL_TICKET_LEN sizeof(InternalTicket)
#else
#define WOLFSSL_INTERNAL_TICKET_LEN \
(((sizeof(InternalTicket) + 15) / 16) * 16)
#endif

#ifndef WOLFSSL_TICKET_EXTRA_PADDING_SZ
#define WOLFSSL_TICKET_EXTRA_PADDING_SZ 32
#endif
Expand Down
26 changes: 24 additions & 2 deletions wolfssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4140,7 +4140,25 @@ WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl);
#ifdef HAVE_SESSION_TICKET

#if !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_WOLFSSL_SERVER)
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
#ifdef WOLFSSL_TICKET_ENC_CBC_HMAC
#if defined(WOLFSSL_TICKET_ENC_HMAC_SHA512)
#define WOLFSSL_TICKET_ENC_HMAC WC_HASH_TYPE_SHA512
#define WOLFSSL_TICKET_HMAC_KEY_SZ 64
#elif defined(WOLFSSL_TICKET_ENC_HMAC_SHA384)
#define WOLFSSL_TICKET_ENC_HMAC WC_HASH_TYPE_SHA384
#define WOLFSSL_TICKET_HMAC_KEY_SZ 48
#else
#define WOLFSSL_TICKET_ENC_HMAC WC_HASH_TYPE_SHA256
#define WOLFSSL_TICKET_HMAC_KEY_SZ 32
#endif
#ifdef WOLFSSL_TICKET_ENC_AES256_CBC
#define WOLFSSL_TICKET_KEY_SZ \
(AES_256_KEY_SIZE + WOLFSSL_TICKET_HMAC_KEY_SZ)
#else
#define WOLFSSL_TICKET_KEY_SZ \
(AES_128_KEY_SIZE + WOLFSSL_TICKET_HMAC_KEY_SZ)
#endif
#elif defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
!defined(WOLFSSL_TICKET_ENC_AES128_GCM) && \
!defined(WOLFSSL_TICKET_ENC_AES256_GCM)
#define WOLFSSL_TICKET_KEY_SZ CHACHA20_POLY1305_AEAD_KEYSIZE
Expand Down Expand Up @@ -4171,7 +4189,11 @@ WOLFSSL_API int wolfSSL_send_SessionTicket(WOLFSSL* ssl);

#define WOLFSSL_TICKET_NAME_SZ 16
#define WOLFSSL_TICKET_IV_SZ 16
#define WOLFSSL_TICKET_MAC_SZ 32
#ifndef WOLFSSL_TICKET_ENC_CBC_HMAC
#define WOLFSSL_TICKET_MAC_SZ 32
#else
#define WOLFSSL_TICKET_MAC_SZ WOLFSSL_TICKET_HMAC_KEY_SZ
#endif

enum TicketEncRet {
WOLFSSL_TICKET_RET_FATAL = -1, /* fatal error, don't use ticket */
Expand Down