Add support for Encrypt-Then-MAC to TLS 1.2 and below

An extension is used to indicate that ETM is to be used.
Only used when doing block ciphers - HMAC performed on encrypted data.
pull/2424/head
Sean Parkinson 2019-08-22 09:33:38 +10:00
parent a49f447e47
commit 24e98dd05e
11 changed files with 1078 additions and 114 deletions

View File

@ -2936,6 +2936,19 @@ then
AM_CFLAGS="$AM_CFLAGS -DHAVE_EXTENDED_MASTER"
fi
# Encrypt-Then-Mac
AC_ARG_ENABLE([enc-then-mac],
[AS_HELP_STRING([--enable-enc-then-mac],[Enable Encryptr-Then-Mac extension (default: enabled)])],
[ ENABLED_ENCRYPT_THEN_MAC=$enableval ],
[ ENABLED_ENCRYPT_THEN_MAC=yes ]
)
if test "x$ENABLED_ENCRYPT_THEN_MAC" = "xyes"
then
AM_CFLAGS="$AM_CFLAGS -DHAVE_ENCRYPT_THEN_MAC"
fi
# TLS Extensions
AC_ARG_ENABLE([tlsx],
[AS_HELP_STRING([--enable-tlsx],[Enable all TLS Extensions (default: disabled)])],
@ -2955,7 +2968,8 @@ then
ENABLED_TRUNCATED_HMAC=yes
ENABLED_ALPN=yes
ENABLED_TRUSTED_CA=yes
AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA"
ENABLED_ENCRYPT_THEN_MAC=yes
AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA -DHAVE_ENCRYPT_THEN_MAC"
# Check the ECC supported curves prereq
AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"],
[ENABLED_SUPPORTED_CURVES=yes

View File

@ -940,7 +940,7 @@ static const char* client_usage_msg[][59] = {
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
"-W <num> Use OCSP Stapling (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */
#endif
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
"-U Atomic User Record Layer Callbacks\n", /* 42 */
#endif
#ifdef HAVE_PK_CALLBACKS
@ -959,41 +959,42 @@ static const char* client_usage_msg[][59] = {
"-q <file> Whitewood config file, defaults\n", /* 47 */
#endif
"-H <arg> Internal tests"
" [defCipherList, exitWithRet, verifyFail]\n", /* 48 */
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 48 */
" loadSSL, disallowETM]\n", /* 49 */
#ifdef WOLFSSL_TLS13
"-J Use HelloRetryRequest to choose group for KE\n", /* 49 */
"-K Key Exchange for PSK not using (EC)DHE\n", /* 50 */
"-I Update keys and IVs before sending data\n", /* 51 */
"-J Use HelloRetryRequest to choose group for KE\n", /* 50 */
"-K Key Exchange for PSK not using (EC)DHE\n", /* 51 */
"-I Update keys and IVs before sending data\n", /* 52 */
#ifndef NO_DH
"-y Key Share with FFDHE named groups only\n", /* 52 */
"-y Key Share with FFDHE named groups only\n", /* 53 */
#endif
#ifdef HAVE_ECC
"-Y Key Share with ECC named groups only\n", /* 53 */
"-Y Key Share with ECC named groups only\n", /* 54 */
#endif
#endif /* WOLFSSL_TLS13 */
#ifdef HAVE_CURVE25519
"-t Use X25519 for key exchange\n", /* 54 */
"-t Use X25519 for key exchange\n", /* 55 */
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
"-Q Support requesting certificate post-handshake\n", /* 55 */
"-Q Support requesting certificate post-handshake\n", /* 56 */
#endif
#ifdef WOLFSSL_EARLY_DATA
"-0 Early data sent to server (0-RTT handshake)\n", /* 56 */
"-0 Early data sent to server (0-RTT handshake)\n", /* 57 */
#endif
#ifdef WOLFSSL_MULTICAST
"-3 <grpid> Multicast, grpid < 256\n", /* 57 */
"-3 <grpid> Multicast, grpid < 256\n", /* 58 */
#endif
"-1 <num> Display a result by specified language.\n"
" 0: English, 1: Japanese\n", /* 58 */
" 0: English, 1: Japanese\n", /* 59 */
#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
"-2 Disable DH Prime check\n", /* 59 */
"-2 Disable DH Prime check\n", /* 60 */
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
"-4 Use resumption for renegotiation\n", /* 60 */
"-4 Use resumption for renegotiation\n", /* 61 */
#endif
#ifdef HAVE_TRUSTED_CA
"-5 Use Trusted CA Key Indication\n", /* 61 */
"-5 Use Trusted CA Key Indication\n", /* 62 */
#endif
NULL,
},
@ -1099,7 +1100,7 @@ static const char* client_usage_msg[][59] = {
"-W <num> OCSP Staplingを使用する"
" (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */
#endif
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
"-U アトミック・ユーザー記録の"
"コールバックを利用する\n", /* 42 */
#endif
@ -1119,42 +1120,43 @@ static const char* client_usage_msg[][59] = {
"-q <file> Whitewood コンフィグファイル, 既定値\n", /* 47 */
#endif
"-H <arg> 内部テスト"
" [defCipherList, exitWithRet, verifyFail]\n", /* 48 */
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 48 */
" loadSSL, disallowETM]\n", /* 49 */
#ifdef WOLFSSL_TLS13
"-J HelloRetryRequestをKEのグループ選択に使用する\n", /* 49 */
"-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 50 */
"-I データ送信前に、鍵とIVを更新する\n", /* 51 */
"-J HelloRetryRequestをKEのグループ選択に使用する\n", /* 50 */
"-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 51 */
"-I データ送信前に、鍵とIVを更新する\n", /* 52 */
#ifndef NO_DH
"-y FFDHE名前付きグループとの鍵共有のみ\n", /* 52 */
"-y FFDHE名前付きグループとの鍵共有のみ\n", /* 53 */
#endif
#ifdef HAVE_ECC
"-Y ECC名前付きグループとの鍵共有のみ\n", /* 53 */
"-Y ECC名前付きグループとの鍵共有のみ\n", /* 54 */
#endif
#endif /* WOLFSSL_TLS13 */
#ifdef HAVE_CURVE25519
"-t X25519を鍵交換に使用する\n", /* 54 */
"-t X25519を鍵交換に使用する\n", /* 55 */
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
"-Q ポストハンドシェークの証明要求をサポートする\n", /* 55 */
"-Q ポストハンドシェークの証明要求をサポートする\n", /* 56 */
#endif
#ifdef WOLFSSL_EARLY_DATA
"-0 Early data をサーバーへ送信する"
"0-RTTハンドシェイク\n", /* 56 */
"0-RTTハンドシェイク\n", /* 57 */
#endif
#ifdef WOLFSSL_MULTICAST
"-3 <grpid> マルチキャスト, grpid < 256\n", /* 57 */
"-3 <grpid> マルチキャスト, grpid < 256\n", /* 58 */
#endif
"-1 <num> 指定された言語で結果を表示します。\n"
" 0: 英語、 1: 日本語\n", /* 58 */
" 0: 英語、 1: 日本語\n", /* 59 */
#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
"-2 DHプライム番号チェックを無効にする\n", /* 59 */
"-2 DHプライム番号チェックを無効にする\n", /* 60 */
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
"-4 再交渉に再開を使用\n", /* 60 */
"-4 再交渉に再開を使用\n", /* 61 */
#endif
#ifdef HAVE_TRUSTED_CA
"-5 信頼できる認証局の鍵表示を使用する\n", /* 61 */
"-5 信頼できる認証局の鍵表示を使用する\n", /* 62 */
#endif
NULL,
},
@ -1258,7 +1260,7 @@ static void Usage(void)
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
printf("%s", msg[++msgid]); /* -W */
#endif
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
printf("%s", msg[++msgid]); /* -U */
#endif
#ifdef HAVE_PK_CALLBACKS
@ -1277,6 +1279,7 @@ static void Usage(void)
printf("%s %s\n", msg[++msgid], wnrConfig); /* -q */
#endif
printf("%s", msg[++msgid]); /* -H */
printf("%s", msg[++msgid]); /* more -H options */
#ifdef WOLFSSL_TLS13
printf("%s", msg[++msgid]); /* -J */
printf("%s", msg[++msgid]); /* -K */
@ -1439,6 +1442,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int exitWithRet = 0;
int loadCertKeyIntoSSLObj = 0;
#ifdef HAVE_ENCRYPT_THEN_MAC
int disallowETM = 0;
#endif
#ifdef HAVE_WNR
const char* wnrConfigFile = wnrConfig;
#endif
@ -1580,7 +1587,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
break;
case 'U' :
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
atomicUser = 1;
#endif
break;
@ -1662,6 +1669,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
printf("Certs turned off with NO_CERTS!\n");
#endif
}
else if (XSTRNCMP(myoptarg, "disallowETM", 7) == 0) {
printf("Disallow Enrypt-Then-MAC\n");
#ifdef HAVE_ENCRYPT_THEN_MAC
disallowETM = 1;
#endif
}
else {
Usage();
XEXIT_T(MY_EX_USAGE);
@ -2699,6 +2712,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
wolfSSL_SetEnableDhKeyTest(ssl, 0);
#endif
#ifdef HAVE_ENCRYPT_THEN_MAC
if (disallowETM)
wolfSSL_AllowEncryptThenMac(ssl, 0);
#endif
tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
@ -2749,7 +2767,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
}
}
#endif
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
if (atomicUser)
SetupAtomicUser(ctx, ssl);
#endif
@ -2973,7 +2991,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE)
wolfSSL_shutdown(ssl); /* bidirectional shutdown */
}
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
if (atomicUser)
FreeAtomicUser(ssl);
#endif

View File

@ -582,39 +582,40 @@ static const char* server_usage_msg[][49] = {
"-g Return basic HTML web page\n", /* 35 */
"-C <num> The number of connections to accept, default: 1\n",/* 36 */
"-H <arg> Internal tests"
" [defCipherList, exitWithRet, verifyFail]\n", /* 37 */
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */
" loadSSL, disallowETM]\n", /* 38 */
#ifdef WOLFSSL_TLS13
"-U Update keys and IVs before sending\n", /* 38 */
"-K Key Exchange for PSK not using (EC)DHE\n", /* 39 */
"-U Update keys and IVs before sending\n", /* 39 */
"-K Key Exchange for PSK not using (EC)DHE\n", /* 40 */
#ifndef NO_DH
"-y Pre-generate Key Share using FFDHE_2048 only\n", /* 40 */
"-y Pre-generate Key Share using FFDHE_2048 only\n", /* 41 */
#endif
#ifdef HAVE_ECC
"-Y Pre-generate Key Share using P-256 only \n", /* 41 */
"-Y Pre-generate Key Share using P-256 only \n", /* 42 */
#endif
#ifdef HAVE_CURVE25519
"-t Pre-generate Key share using Curve25519 only\n", /* 42 */
"-t Pre-generate Key share using Curve25519 only\n", /* 43 */
#endif
#ifdef HAVE_SESSION_TICKET
"-T Do not generate session ticket\n", /* 43 */
"-T Do not generate session ticket\n", /* 44 */
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
"-Q Request certificate from client post-handshake\n", /* 44 */
"-Q Request certificate from client post-handshake\n", /* 45 */
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
"-J Server sends Cookie Extension containing state\n", /* 45 */
"-J Server sends Cookie Extension containing state\n", /* 46 */
#endif
#endif /* WOLFSSL_TLS13 */
#ifdef WOLFSSL_EARLY_DATA
"-0 Early data read from client (0-RTT handshake)\n", /* 46 */
"-0 Early data read from client (0-RTT handshake)\n", /* 47 */
#endif
#ifdef WOLFSSL_MULTICAST
"-3 <grpid> Multicast, grpid < 256\n", /* 47 */
"-3 <grpid> Multicast, grpid < 256\n", /* 48 */
#endif
"-1 <num> Display a result by specified language."
"\n 0: English, 1: Japanese\n", /* 48 */
"\n 0: English, 1: Japanese\n", /* 49 */
#ifdef HAVE_TRUSTED_CA
"-5 Use Trusted CA Key Indication\n", /* 51 */
"-5 Use Trusted CA Key Indication\n", /* 52 */
#endif
NULL,
},
@ -698,41 +699,42 @@ static const char* server_usage_msg[][49] = {
"-g 基本的な Web ページを返す\n", /* 35 */
"-C <num> アクセプト可能な接続数を指定する。既定値: 1\n", /* 36 */
"-H <arg> 内部テスト"
" [defCipherList, exitWithRet, verifyFail]\n", /* 37 */
" [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */
" loadSSL, disallowETM]\n", /* 38 */
#ifdef WOLFSSL_TLS13
"-U データ送信前に、鍵とIVを更新する\n", /* 38 */
"-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 39 */
"-U データ送信前に、鍵とIVを更新する\n", /* 39 */
"-K 鍵交換にPSKを使用、(EC)DHEは使用しない\n", /* 40 */
#ifndef NO_DH
"-y FFDHE_2048のみを使用して鍵共有を事前生成する\n", /* 40 */
"-y FFDHE_2048のみを使用して鍵共有を事前生成する\n", /* 41 */
#endif
#ifdef HAVE_ECC
"-Y P-256のみを使用したキー共有の事前生成\n", /* 41 */
"-Y P-256のみを使用したキー共有の事前生成\n", /* 42 */
#endif
#ifdef HAVE_CURVE25519
"-t Curve25519のみを使用して鍵共有を事前生成する\n", /* 42 */
"-t Curve25519のみを使用して鍵共有を事前生成する\n", /* 43 */
#endif
#ifdef HAVE_SESSION_TICKET
"-T セッションチケットを生成しない\n", /* 43 */
"-T セッションチケットを生成しない\n", /* 44 */
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
"-Q クライアントのポストハンドシェイクから"
"証明書を要求する\n", /* 44 */
"証明書を要求する\n", /* 45 */
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
"-J サーバーの状態を含むTLS Cookie 拡張を送信する\n", /* 45 */
"-J サーバーの状態を含むTLS Cookie 拡張を送信する\n", /* 46 */
#endif
#endif /* WOLFSSL_TLS13 */
#ifdef WOLFSSL_EARLY_DATA
"-0 クライアントからの Early Data 読み取り"
"0-RTTハンドシェイク\n", /* 46 */
"0-RTTハンドシェイク\n", /* 47 */
#endif
#ifdef WOLFSSL_MULTICAST
"-3 <grpid> マルチキャスト, grpid < 256\n", /* 47 */
"-3 <grpid> マルチキャスト, grpid < 256\n", /* 48 */
#endif
"-1 <num> 指定された言語で結果を表示します。"
"\n 0: 英語、 1: 日本語\n", /* 48 */
"\n 0: 英語、 1: 日本語\n", /* 49 */
#ifdef HAVE_TRUSTED_CA
"-5 信頼できる認証局の鍵表示を使用する\n", /* 51 */
"-5 信頼できる認証局の鍵表示を使用する\n", /* 52 */
#endif
NULL,
},
@ -812,7 +814,8 @@ static void Usage(void)
#endif
printf("%s", msg[++msgId]); /* -g */
printf("%s", msg[++msgId]); /* -C */
printf("%s", msg[++msgId]); /* -H */
printf("%s", msg[++msgId]); /* -H */
printf("%s", msg[++msgId]); /* more -H options */
#ifdef WOLFSSL_TLS13
printf("%s", msg[++msgId]); /* -U */
printf("%s", msg[++msgId]); /* -K */
@ -997,6 +1000,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
int exitWithRet = 0;
int loadCertKeyIntoSSLObj = 0;
#ifdef HAVE_ENCRYPT_THEN_MAC
int disallowETM = 0;
#endif
((func_args*)args)->return_code = -1; /* error state */
#ifdef NO_RSA
@ -1173,6 +1180,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
loadCertKeyIntoSSLObj = 1;
#endif
}
else if (XSTRNCMP(myoptarg, "disallowETM", 11) == 0) {
printf("Disallow Encrypt-Then-MAC\n");
#ifdef HAVE_ENCRYPT_THEN_MAC
disallowETM = 1;
#endif
}
else {
Usage();
XEXIT_T(MY_EX_USAGE);
@ -1979,6 +1992,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
}
#endif
#ifdef HAVE_ENCRYPT_THEN_MAC
if (disallowETM)
wolfSSL_AllowEncryptThenMac(ssl, 0);
#endif
/* do accept */
readySignal = ((func_args*)args)->signal;

View File

@ -141,6 +141,7 @@ enum processReply {
#endif
getRecordLayerHeader,
getData,
verifyEncryptedMessage,
decryptMessage,
verifyMessage,
runProcessingOneMessage
@ -3373,6 +3374,20 @@ static void SetDigest(WOLFSSL* ssl, int hashAlgo)
#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
#endif /* !NO_CERTS */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
static word32 MacSize(WOLFSSL* ssl)
{
#ifdef HAVE_TRUNCATED_HMAC
word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
: ssl->specs.hash_size;
#else
word32 digestSz = ssl->specs.hash_size;
#endif
return digestSz;
}
#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
#ifndef NO_RSA
#ifndef WOLFSSL_NO_TLS12
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
@ -5133,6 +5148,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#endif
#endif /* HAVE_TLS_EXTENSIONS */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
#endif
/* default alert state (none) */
ssl->alert_history.last_rx.code = -1;
ssl->alert_history.last_rx.level = -1;
@ -10481,6 +10500,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (IsEncryptionOn(ssl, 0)) {
args->idx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
args->idx += MacSize(ssl);
#endif
}
/* Advance state and proceed */
@ -10704,9 +10727,20 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
SendAlert(ssl, alert_fatal, bad_certificate_status_response);
if (IsEncryptionOn(ssl, 0)) {
if (*inOutIdx + ssl->keys.padSz > size)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
if (*inOutIdx + ssl->keys.padSz + digestSz > size)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz + digestSz;
}
else
#endif
{
if (*inOutIdx + ssl->keys.padSz > size)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz;
}
}
WOLFSSL_LEAVE("DoCertificateStatus", ret);
@ -10735,11 +10769,22 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return BUFFER_ERROR;
if (IsEncryptionOn(ssl, 0)) {
/* access beyond input + size should be checked against totalSz */
if (*inOutIdx + ssl->keys.padSz > totalSz)
return BUFFER_E;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz + digestSz;
}
else
#endif
{
/* access beyond input + size should be checked against totalSz */
if (*inOutIdx + ssl->keys.padSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz;
*inOutIdx += ssl->keys.padSz;
}
}
if (ssl->options.side == WOLFSSL_SERVER_END) {
@ -10772,8 +10817,17 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
return BUFFER_ERROR;
/* check against totalSz */
if (*inOutIdx + size + ssl->keys.padSz > totalSz)
return BUFFER_E;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
if (*inOutIdx + size + ssl->keys.padSz + MacSize(ssl) > totalSz)
return BUFFER_E;
}
else
#endif
{
if (*inOutIdx + size + ssl->keys.padSz > totalSz)
return BUFFER_E;
}
#ifdef WOLFSSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
@ -10805,6 +10859,10 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
/* force input exhaustion at ProcessReply consuming padSz */
*inOutIdx += size + ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
*inOutIdx += MacSize(ssl);
#endif
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
@ -11192,6 +11250,10 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
expectedIdx = *inOutIdx + size +
(ssl->keys.encryptionOn ? ssl->keys.padSz : 0);
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac && ssl->keys.encryptionOn)
expectedIdx += MacSize(ssl);
#endif
#if !defined(WOLFSSL_NO_SERVER) && \
defined(HAVE_SECURE_RENEGOTIATION) && \
@ -11369,6 +11431,10 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
*inOutIdx += MacSize(ssl);
#endif
}
if (ssl->options.resuming) {
WOLFSSL_MSG("Not resuming as thought");
@ -11402,11 +11468,23 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
if (IsEncryptionOn(ssl, 0)) {
/* access beyond input + size should be checked against totalSz */
if (*inOutIdx + ssl->keys.padSz > totalSz)
return BUFFER_E;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz + digestSz;
}
else
#endif
{
/* access beyond input + size should be checked against totalSz
*/
if (*inOutIdx + ssl->keys.padSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz;
*inOutIdx += ssl->keys.padSz;
}
}
break;
@ -11917,11 +11995,22 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* Already saw this message and processed it. It can be ignored. */
*inOutIdx += fragSz;
if(type == finished ) {
if (*inOutIdx + ssl->keys.padSz > totalSz) {
WOLFSSL_ERROR(BUFFER_E);
return BUFFER_E;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
return BUFFER_E;
*inOutIdx += ssl->keys.padSz + digestSz;
}
else
#endif
{
if (*inOutIdx + ssl->keys.padSz > totalSz) {
WOLFSSL_ERROR(BUFFER_E);
return BUFFER_E;
}
*inOutIdx += ssl->keys.padSz;
}
*inOutIdx += ssl->keys.padSz;
}
if (IsDtlsNotSctpMode(ssl) &&
VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) {
@ -12921,6 +13010,15 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type == block) {
#ifdef HAVE_ENCRYPT_THEN_MAC
if (ssl->options.encThenMac) {
if ((encryptSz - MacSize(ssl)) % ssl->specs.block_size) {
WOLFSSL_MSG("Block ciphertext not block size");
return SANITY_CIPHER_E;
}
}
else
#endif
if (encryptSz % ssl->specs.block_size) {
WOLFSSL_MSG("Block ciphertext not block size");
return SANITY_CIPHER_E;
@ -13127,6 +13225,10 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
}
dataSz = msgSz - ivExtra - ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
dataSz -= MacSize(ssl);
#endif
if (dataSz < 0) {
WOLFSSL_MSG("App data buffer error, malicious input?");
SendAlert(ssl, alert_fatal, unexpected_message);
@ -13159,6 +13261,10 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
}
idx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
idx += MacSize(ssl);
#endif
#ifdef HAVE_LIBZ
/* decompress could be bigger, overwrite after verify */
@ -13189,8 +13295,13 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
READ_PROTO, ssl->heap);
#endif
if (IsEncryptionOn(ssl, 0))
if (IsEncryptionOn(ssl, 0)) {
dataSz -= ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
dataSz -= MacSize(ssl);
#endif
}
/* make sure can read the message */
if (dataSz != ALERT_SIZE) {
@ -13232,8 +13343,13 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type,
}
#endif
WOLFSSL_ERROR(*type);
if (IsEncryptionOn(ssl, 0))
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
*inOutIdx += MacSize(ssl);
#endif
}
return level;
}
@ -13311,6 +13427,30 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
return 0;
}
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz,
int content)
{
int ret;
#ifdef HAVE_TRUNCATED_HMAC
word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
: ssl->specs.hash_size;
#else
word32 digestSz = ssl->specs.hash_size;
#endif
byte verify[WC_MAX_DIGEST_SIZE];
WOLFSSL_MSG("Verify MAC of Encrypted Data");
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz);
if (ret != 0) {
return VERIFY_MAC_ERROR;
}
return 0;
}
#endif
static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
int content, word32* padSz)
@ -13611,10 +13751,49 @@ int ProcessReply(WOLFSSL* ssl)
}
ssl->keys.padSz = 0;
ssl->options.processReply = decryptMessage;
ssl->options.processReply = verifyEncryptedMessage;
startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
FALL_THROUGH;
/* verify digest of encrypted message */
case verifyEncryptedMessage:
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 &&
!atomicUser && ssl->options.encThenMac) {
ret = VerifyMacEnc(ssl, ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->curSize, ssl->curRL.type);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E)
return ret;
#endif
if (ret < 0) {
WOLFSSL_MSG("VerifyMacEnc failed");
WOLFSSL_ERROR(ret);
#ifdef WOLFSSL_DTLS
/* If in DTLS mode, if the decrypt fails for any
* reason, pretend the datagram never happened. */
if (ssl->options.dtls) {
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.idx =
ssl->buffers.inputBuffer.length;
#ifdef WOLFSSL_DTLS_DROP_STATS
ssl->macDropCount++;
#endif /* WOLFSSL_DTLS_DROP_STATS */
}
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_EXTRA_ALERTS
if (!ssl->options.dtls)
SendAlert(ssl, alert_fatal, bad_record_mac);
#endif
return DECRYPT_ERROR;
}
ssl->keys.encryptSz = ssl->curSize;
}
#endif
ssl->options.processReply = decryptMessage;
FALL_THROUGH;
/* decrypt message */
case decryptMessage:
@ -13637,24 +13816,52 @@ int ProcessReply(WOLFSSL* ssl)
}
if (atomicUser) {
#ifdef ATOMIC_USER
ret = ssl->ctx->DecryptVerifyCb(ssl,
in->buffer + in->idx,
in->buffer + in->idx,
ssl->curSize, ssl->curRL.type, 1,
&ssl->keys.padSz, ssl->DecryptVerifyCtx);
#endif /* ATOMIC_USER */
#ifdef ATOMIC_USER
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
ret = ssl->ctx->VerifyDecryptCb(ssl,
in->buffer + in->idx, in->buffer + in->idx,
ssl->curSize - MacSize(ssl),
ssl->curRL.type, 1, &ssl->keys.padSz,
ssl->DecryptVerifyCtx);
}
else
#endif
{
ret = ssl->ctx->DecryptVerifyCb(ssl,
in->buffer + in->idx,
in->buffer + in->idx,
ssl->curSize, ssl->curRL.type, 1,
&ssl->keys.padSz, ssl->DecryptVerifyCtx);
}
#endif /* ATOMIC_USER */
}
else {
if (!ssl->options.tls1_3) {
#ifndef WOLFSSL_NO_TLS12
#ifndef WOLFSSL_NO_TLS12
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
ret = Decrypt(ssl,
in->buffer + in->idx,
in->buffer + in->idx,
ssl->curSize - digestSz);
ssl->keys.padSz =
in->buffer[in->idx + ssl->curSize - digestSz - 1];
ssl->keys.padSz += 1;
ssl->keys.decryptedCur = 1;
}
else
#endif
{
ret = Decrypt(ssl,
in->buffer + in->idx,
in->buffer + in->idx,
ssl->curSize);
#else
}
#else
ret = DECRYPT_ERROR;
#endif
#endif
}
else
{
@ -13743,7 +13950,11 @@ int ProcessReply(WOLFSSL* ssl)
ssl->curRL.type != change_cipher_spec))
#endif
{
if (!atomicUser) {
if (!atomicUser
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
&& !ssl->options.encThenMac
#endif
) {
ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.idx,
ssl->curSize, ssl->curRL.type,
@ -13940,6 +14151,13 @@ int ProcessReply(WOLFSSL* ssl)
if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
ssl->buffers.inputBuffer.idx += digestSz;
ssl->curSize -= digestSz;
}
#endif
}
if (ssl->curSize != 1) {
@ -14054,12 +14272,29 @@ int ProcessReply(WOLFSSL* ssl)
if (IsEncryptionOn(ssl, 0)) {
WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
word32 digestSz = MacSize(ssl);
if (ssl->buffers.inputBuffer.idx >=
ssl->keys.padSz + digestSz) {
ssl->buffers.inputBuffer.idx -=
ssl->keys.padSz + digestSz;
}
else {
WOLFSSL_MSG("\tmiddle padding error");
return FATAL_ERROR;
}
}
else {
WOLFSSL_MSG("\tmiddle padding error");
return FATAL_ERROR;
else
#endif
{
if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
}
else {
WOLFSSL_MSG("\tmiddle padding error");
return FATAL_ERROR;
}
}
}
@ -14563,7 +14798,14 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
ERROR_OUT(BUFFER_E, exit_buildmsg);
}
args->sz += 1; /* pad byte */
args->pad = (args->sz - args->headerSz) % blockSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
args->pad = (args->sz - args->headerSz -
args->digestSz) % blockSz;
}
else
#endif
args->pad = (args->sz - args->headerSz) % blockSz;
#ifdef OPENSSL_EXTRA
if(args->pad != 0)
#endif
@ -14634,9 +14876,16 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
}
#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type == block) {
word32 tmpIdx = args->idx + args->digestSz;
word32 tmpIdx;
word32 i;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
tmpIdx = args->idx;
else
#endif
tmpIdx = args->idx + args->digestSz;
for (i = 0; i <= args->pad; i++)
output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */
}
@ -14648,18 +14897,39 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
case BUILD_MSG_VERIFY_MAC:
{
/* User Record Layer Callback handling */
#ifdef ATOMIC_USER
if (ssl->ctx->MacEncryptCb) {
ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
output + args->headerSz + args->ivSz, inSz, type, 0,
output + args->headerSz, output + args->headerSz, args->size,
ssl->MacEncryptCtx);
goto exit_buildmsg;
#ifdef ATOMIC_USER
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
if (ssl->ctx->EncryptMacCb) {
ret = ssl->ctx->EncryptMacCb(ssl, output + args->idx +
args->pad + 1, type, 0,
output + args->headerSz,
output + args->headerSz,
args->size - args->digestSz,
ssl->MacEncryptCtx);
goto exit_buildmsg;
}
}
else
#endif
{
if (ssl->ctx->MacEncryptCb) {
ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
output + args->headerSz + args->ivSz, inSz,
type, 0, output + args->headerSz,
output + args->headerSz, args->size,
ssl->MacEncryptCtx);
goto exit_buildmsg;
}
}
#endif
#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type != aead) {
if (ssl->specs.cipher_type != aead
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
&& !ssl->options.encThenMac
#endif
) {
#ifdef HAVE_TRUNCATED_HMAC
if (ssl->truncated_hmac &&
ssl->specs.hash_size > args->digestSz) {
@ -14701,9 +14971,65 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
FALL_THROUGH;
case BUILD_MSG_ENCRYPT:
{
ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size,
asyncOkay);
break;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
ret = Encrypt(ssl, output + args->headerSz,
output + args->headerSz,
args->size - args->digestSz, asyncOkay);
}
else
#endif
{
ret = Encrypt(ssl, output + args->headerSz,
output + args->headerSz, args->size, asyncOkay);
}
if (ret != 0)
goto exit_buildmsg;
ssl->options.buildMsgState = BUILD_MSG_ENCRYPTED_VERIFY_MAC;
}
FALL_THROUGH;
case BUILD_MSG_ENCRYPTED_VERIFY_MAC:
{
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac) {
WOLFSSL_MSG("Calculate MAC of Encrypted Data");
#ifdef HAVE_TRUNCATED_HMAC
if (ssl->truncated_hmac &&
ssl->specs.hash_size > args->digestSz) {
#ifdef WOLFSSL_SMALL_STACK
byte* hmac = NULL;
#else
byte hmac[WC_MAX_DIGEST_SIZE];
#endif
#ifdef WOLFSSL_SMALL_STACK
hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
DYNAMIC_TYPE_DIGEST);
if (hmac == NULL)
ERROR_OUT(MEMORY_E, exit_buildmsg);
#endif
ret = ssl->hmac(ssl, hmac, output + args->headerSz,
args->ivSz + inSz + args->pad + 1, -1, type,
0);
XMEMCPY(output + args->idx + args->pad + 1, hmac,
args->digestSz);
#ifdef WOLFSSL_SMALL_STACK
XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
#endif
}
else
#endif
{
ret = ssl->hmac(ssl, output + args->idx + args->pad + 1,
output + args->headerSz,
args->ivSz + inSz + args->pad + 1, -1, type,
0);
}
}
#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
}
}
@ -18396,6 +18722,10 @@ exit_dpk:
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac && ssl->specs.cipher_type == block)
*inOutIdx += MacSize(ssl);
#endif
}
#ifdef HAVE_SECRET_CALLBACK
@ -18652,8 +18982,13 @@ exit_dpk:
ssl->options.sendVerify = SEND_BLANK_CERT;
}
if (IsEncryptionOn(ssl, 0))
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
*inOutIdx += MacSize(ssl);
#endif
}
WOLFSSL_LEAVE("DoCertificateRequest", 0);
WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
@ -19680,6 +20015,10 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
{
if (IsEncryptionOn(ssl, 0)) {
args->idx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
args->idx += MacSize(ssl);
#endif
}
/* QSH extensions */
@ -21824,6 +22163,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
*inOutIdx += MacSize(ssl);
#endif
}
ssl->expect_session_ticket = 0;
@ -25019,6 +25362,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
{
if (IsEncryptionOn(ssl, 0)) {
args->idx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
args->idx += MacSize(ssl);
#endif
}
ssl->options.havePeerVerify = 1;
@ -26625,6 +26972,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
{
if (IsEncryptionOn(ssl, 0)) {
args->idx += ssl->keys.padSz;
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.encThenMac)
args->idx += MacSize(ssl);
#endif
}
#ifdef HAVE_QSH

View File

@ -2208,6 +2208,11 @@ int SetCipherSpecs(WOLFSSL* ssl)
#endif
}
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (IsAtLeastTLSv1_3(ssl->version) || ssl->specs.cipher_type != block)
ssl->options.encThenMac = 0;
#endif
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.dtls)
ssl->hmac = TLS_hmac;

111
src/ssl.c
View File

@ -3057,6 +3057,84 @@ void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl)
return NULL;
}
/**
* Set the callback, against the context, that encrypts then MACs.
*
* ctx SSL/TLS context.
* cb Callback function to use with Encrypt-Then-MAC.
*/
void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX* ctx, CallbackEncryptMac cb)
{
if (ctx)
ctx->EncryptMacCb = cb;
}
/**
* Set the context to use with callback that encrypts then MACs.
*
* ssl SSL/TLS object.
* ctx Callback function's context.
*/
void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
ssl->EncryptMacCtx = ctx;
}
/**
* Get the context being used with callback that encrypts then MACs.
*
* ssl SSL/TLS object.
* returns callback function's context or NULL if SSL/TLS object is NULL.
*/
void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl)
{
if (ssl)
return ssl->EncryptMacCtx;
return NULL;
}
/**
* Set the callback, against the context, that MAC verifies then decrypts.
*
* ctx SSL/TLS context.
* cb Callback function to use with Encrypt-Then-MAC.
*/
void wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX* ctx, CallbackVerifyDecrypt cb)
{
if (ctx)
ctx->VerifyDecryptCb = cb;
}
/**
* Set the context to use with callback that MAC verifies then decrypts.
*
* ssl SSL/TLS object.
* ctx Callback function's context.
*/
void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx)
{
if (ssl)
ssl->VerifyDecryptCtx = ctx;
}
/**
* Get the context being used with callback that MAC verifies then decrypts.
*
* ssl SSL/TLS object.
* returns callback function's context or NULL if SSL/TLS object is NULL.
*/
void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl)
{
if (ssl)
return ssl->VerifyDecryptCtx;
return NULL;
}
const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl)
{
@ -3125,10 +3203,12 @@ int wolfSSL_GetCipherType(WOLFSSL* ssl)
if (ssl == NULL)
return BAD_FUNC_ARG;
#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type == block)
return WOLFSSL_BLOCK_TYPE;
if (ssl->specs.cipher_type == stream)
return WOLFSSL_STREAM_TYPE;
#endif
if (ssl->specs.cipher_type == aead)
return WOLFSSL_AEAD_TYPE;
@ -38027,3 +38107,34 @@ int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
return wolfSSL_X509_set_pubkey(req, pkey);
}
#endif
#ifdef HAVE_ENCRYPT_THEN_MAC
/**
* Sets whether Encrypt-Then-MAC extension can be negotitated against context.
* The default value: enabled.
*
* ctx SSL/TLS context.
* set Whether to allow or not: 1 is allow and 0 is disallow.
* returns WOLFSSL_SUCCESS
*/
int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *ctx, int set)
{
ctx->disallowEncThenMac = !set;
return WOLFSSL_SUCCESS;
}
/**
* Sets whether Encrypt-Then-MAC extension can be negotitated against context.
* The default value comes from context.
*
* ctx SSL/TLS context.
* set Whether to allow or not: 1 is allow and 0 is disallow.
* returns WOLFSSL_SUCCESS
*/
int wolfSSL_AllowEncryptThenMac(WOLFSSL *ssl, int set)
{
ssl->options.disallowEncThenMac = !set;
return WOLFSSL_SUCCESS;
}
#endif

178
src/tls.c
View File

@ -5568,6 +5568,148 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz,
#endif /* HAVE_QSH */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
/******************************************************************************/
/* Encrypt-then-MAC */
/******************************************************************************/
#ifndef WOLFSSL_NO_TLS12
static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl);
/**
* Get the size of the Encrypt-Then-MAC extension.
*
* msgType Type of message to put extension into.
* pSz Size of extension data.
* return SANITY_MSG_E when the message is not allowed to have extension and
* 0 otherwise.
*/
static int TLSX_EncryptThenMac_GetSize(byte msgType, word16* pSz)
{
(void)pSz;
if (msgType != client_hello && msgType != server_hello) {
return SANITY_MSG_E;
}
/* Empty extension */
return 0;
}
/**
* Write the Encrypt-Then-MAC extension.
*
* data Unused
* output Extension data buffer. Unused.
* msgType Type of message to put extension into.
* pSz Size of extension data.
* return SANITY_MSG_E when the message is not allowed to have extension and
* 0 otherwise.
*/
static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType,
word16* pSz)
{
(void)data;
(void)output;
(void)pSz;
if (msgType != client_hello && msgType != server_hello) {
return SANITY_MSG_E;
}
/* Empty extension */
return 0;
}
/**
* Parse the Encrypt-Then-MAC extension.
*
* ssl SSL object
* input Extension data buffer.
* length Length of this extension's data.
* msgType Type of message to extension appeared in.
* return SANITY_MSG_E when the message is not allowed to have extension,
* BUFFER_ERROR when the extension's data is invalid,
* MEMORY_E when unable to allocate memory and
* 0 otherwise.
*/
static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte msgType)
{
int ret;
(void)input;
if (msgType != client_hello && msgType != server_hello) {
return SANITY_MSG_E;
}
/* Empty extension */
if (length != 0)
return BUFFER_ERROR;
if (msgType == client_hello) {
/* Check the user hasn't disallowed use of Encrypt-Then-Mac. */
if (!ssl->options.disallowEncThenMac) {
ssl->options.encThenMac = 1;
/* Set the extension reply. */
ret = TLSX_EncryptThenMac_Use(ssl);
if (ret != 0)
return ret;
TLSX_SetResponse(ssl, TLSX_ENCRYPT_THEN_MAC);
}
return 0;
}
/* Server Hello */
if (ssl->options.disallowEncThenMac)
return SANITY_MSG_E;
ssl->options.encThenMac = 1;
return 0;
}
/**
* Add the Encrypt-Then-MAC extension to list.
*
* ssl SSL object
* return MEMORY_E when unable to allocate memory and 0 otherwise.
*/
static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl)
{
int ret = 0;
TLSX* extension;
/* Find the Encrypt-Then-Mac extension if it exists. */
extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
if (extension == NULL) {
/* Push new Encrypt-Then-Mac extension. */
ret = TLSX_Push(&ssl->extensions, TLSX_ENCRYPT_THEN_MAC, NULL,
ssl->heap);
if (ret != 0)
return ret;
}
return 0;
}
#define ETM_GET_SIZE TLSX_EncryptThenMac_GetSize
#define ETM_WRITE TLSX_EncryptThenMac_Write
#define ETM_PARSE TLSX_EncryptThenMac_Parse
#else
#define ETM_GET_SIZE(a, b) 0
#define ETM_WRITE(a, b, c, d) 0
#define ETM_PARSE(a, b, c, d) 0
#endif /* !WOLFSSL_NO_TLS12 */
#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
/******************************************************************************/
/* Supported Versions */
/******************************************************************************/
@ -8721,6 +8863,10 @@ void TLSX_FreeAll(TLSX* list, void* heap)
case TLSX_SIGNATURE_ALGORITHMS:
break;
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
case TLSX_ENCRYPT_THEN_MAC:
break;
#endif
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
break;
@ -8858,6 +9004,11 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
length += SA_GET_SIZE(extension->data);
break;
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
case TLSX_ENCRYPT_THEN_MAC:
ret = ETM_GET_SIZE(msgType, &length);
break;
#endif /* HAVE_ENCRYPT_THEN_MAC */
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
ret = SV_GET_SIZE(extension->data, msgType, &length);
@ -9021,6 +9172,12 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
offset += SA_WRITE(extension->data, output + offset);
break;
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
case TLSX_ENCRYPT_THEN_MAC:
WOLFSSL_MSG("Encrypt-Then-Mac extension to write");
ret = ETM_WRITE(extension->data, output, msgType, &offset);
break;
#endif /* HAVE_ENCRYPT_THEN_MAC */
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
WOLFSSL_MSG("Supported Versions extension to write");
@ -9560,6 +9717,14 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
}
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (!ssl->options.disallowEncThenMac) {
ret = TLSX_EncryptThenMac_Use(ssl);
if (ret != 0)
return ret;
}
#endif
#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
defined(HAVE_SUPPORTED_CURVES)
if (!ssl->options.userCurves && !ssl->ctx->userCurves) {
@ -10552,6 +10717,19 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
ret = SA_PARSE(ssl, input + offset, size, isRequest, suites);
break;
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
case TLSX_ENCRYPT_THEN_MAC:
WOLFSSL_MSG("Encrypt-Then-Mac extension received");
/* Ignore for TLS 1.3+ */
if (IsAtLeastTLSv1_3(ssl->version))
break;
ret = ETM_PARSE(ssl, input + offset, size, msgType);
break;
#endif /* HAVE_ENCRYPT_THEN_MAC */
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
WOLFSSL_MSG("Skipping Supported Versions - already processed");

View File

@ -2470,3 +2470,60 @@
# client TLSv1.2 with Trusted CA Indication (pre-shared)
-v 3
-5
# server TLSv1.2 with block cipher and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA256
-H disallowETM
# client TLSv1.2 with block cipher
-v 3
-l ECDHE-RSA-AES128-SHA256
# server TLSv1.2 with block cipher
-v 3
-l ECDHE-RSA-AES128-SHA256
# client TLSv1.2 with block cipher and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA256
-H disallowETM
# server TLSv1.2 with block cipher and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA256
-H disallowETM
# client TLSv1.2 with block cipher and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA256
-H disallowETM
# server TLSv1.2 with block cipher and SHA-1 and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA
-H disallowETM
# client TLSv1.2 with block cipher and SHA-1 and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA
-H disallowETM
# server TLSv1.2 with block cipher
-v 3
-l ECDHE-RSA-AES128-SHA256
# client TLSv1.2 with block cipher - atomic user (use callback)
-v 3
-l ECDHE-RSA-AES128-SHA256
-U
# server TLSv1.2 with block cipher and no ETM
-v 3
-l ECDHE-RSA-AES128-SHA256
-H disallowETM
# client TLSv1.2 with block cipher - atomic user (use callback)
-v 3
-l ECDHE-RSA-AES128-SHA256
-U

View File

@ -2099,6 +2099,9 @@ typedef enum {
#endif
TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
TLSX_ENCRYPT_THEN_MAC = 0x0016, /* RFC 7366 */
#endif
TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */
TLSX_SESSION_TICKET = 0x0023,
#ifdef WOLFSSL_TLS13
@ -2621,6 +2624,9 @@ struct WOLFSSL_CTX {
#ifdef HAVE_SECURE_RENEGOTIATION
byte useSecureReneg:1; /* when set will set WOLFSSL objects generated to enable */
#endif
#ifdef HAVE_ENCRYPT_THEN_MAC
byte disallowEncThenMac:1; /* Don't do Encrypt-Then-MAC */
#endif
#ifdef WOLFSSL_MULTICAST
byte haveMcast; /* multicast requested */
byte mcastID; /* multicast group ID */
@ -2748,6 +2754,10 @@ struct WOLFSSL_CTX {
#ifdef ATOMIC_USER
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */
CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */
#ifdef HAVE_ENCRYPT_THEN_MAC
CallbackEncryptMac EncryptMacCb; /* Atomic User Mac/Enc Cb */
CallbackVerifyDecrypt VerifyDecryptCb; /* Atomic User Dec/Verify Cb */
#endif
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
@ -3228,6 +3238,7 @@ enum buildMsgState {
BUILD_MSG_HASH,
BUILD_MSG_VERIFY_MAC,
BUILD_MSG_ENCRYPT,
BUILD_MSG_ENCRYPTED_VERIFY_MAC,
};
/* sub-states for cipher operations */
@ -3352,6 +3363,10 @@ typedef struct Options {
#ifdef SINGLE_THREADED
word16 ownSuites:1; /* if suites are malloced in ssl object */
#endif
#ifdef HAVE_ENCRYPT_THEN_MAC
word16 disallowEncThenMac:1; /* Don't do Encrypt-Then-MAC */
word16 encThenMac:1; /* Doing Encrypt-Then-MAC */
#endif
/* need full byte values for this section */
byte processReply; /* nonblocking resume */
@ -3985,6 +4000,10 @@ struct WOLFSSL {
#ifdef ATOMIC_USER
void* MacEncryptCtx; /* Atomic User Mac/Encrypt Callback Context */
void* DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */
#ifdef HAVE_ENCRYPT_THEN_MAC
void* EncryptMacCtx; /* Atomic User Encrypt/Mac Callback Ctx */
void* VerifyDecryptCtx; /* Atomic User Verify/Decrypt Callback Ctx */
#endif
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC

View File

@ -1935,10 +1935,26 @@ typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl,
unsigned int decSz, int content, int verify, unsigned int* padSz,
void* ctx);
WOLFSSL_API void wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*,
CallbackDecryptVerify);
CallbackDecryptVerify);
WOLFSSL_API void wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx);
WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl);
typedef int (*CallbackEncryptMac)(WOLFSSL* ssl, unsigned char* macOut,
int content, int macVerify, unsigned char* encOut,
const unsigned char* encIn, unsigned int encSz, void* ctx);
WOLFSSL_API void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX*, CallbackEncryptMac);
WOLFSSL_API void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx);
WOLFSSL_API void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl);
typedef int (*CallbackVerifyDecrypt)(WOLFSSL* ssl,
unsigned char* decOut, const unsigned char* decIn,
unsigned int decSz, int content, int verify, unsigned int* padSz,
void* ctx);
WOLFSSL_API void wolfSSL_CTX_SetVerifyDecryptCb(WOLFSSL_CTX*,
CallbackVerifyDecrypt);
WOLFSSL_API void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx);
WOLFSSL_API void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl);
WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int);
WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*);
WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*);
@ -3186,6 +3202,11 @@ WOLFSSL_API unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x5
WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx);
#endif
#ifdef HAVE_ENCRYPT_THEN_MAC
WOLFSSL_API int wolfSSL_CTX_AllowEncryptThenMac(WOLFSSL_CTX *, int);
WOLFSSL_API int wolfSSL_AllowEncryptThenMac(WOLFSSL *s, int);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -1975,7 +1975,7 @@ static WC_INLINE void StackTrap(void)
#endif /* STACK_TRAP */
#ifdef ATOMIC_USER
#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
/* Atomic Encrypt Context example */
typedef struct AtomicEncCtx {
@ -2016,6 +2016,9 @@ static WC_INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut,
/* hmac, not needed if aead mode */
wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
if (ret != 0)
return ret;
ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl));
if (ret != 0)
@ -2133,6 +2136,9 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl,
wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
if (ret != 0)
return ret;
ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
wolfSSL_GetMacSecret(ssl, macVerify), digestSz);
if (ret != 0)
@ -2156,6 +2162,162 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl,
return ret;
}
#if defined(HAVE_ENCRYPT_THEN_MAC)
static WC_INLINE int myEncryptMacCb(WOLFSSL* ssl, unsigned char* macOut,
int content, int macVerify, unsigned char* encOut,
const unsigned char* encIn, unsigned int encSz, void* ctx)
{
int ret;
Hmac hmac;
AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx;
byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
const char* tlsStr = "TLS";
/* example supports (d)tls aes */
if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) {
printf("myMacEncryptCb not using AES\n");
return -1;
}
if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) {
printf("myMacEncryptCb not using (D)TLS\n");
return -1;
}
/* encrypt setup on first time */
if (encCtx->keySetup == 0) {
int keyLen = wolfSSL_GetKeySize(ssl);
const byte* key;
const byte* iv;
if (wolfSSL_GetSide(ssl) == WOLFSSL_CLIENT_END) {
key = wolfSSL_GetClientWriteKey(ssl);
iv = wolfSSL_GetClientWriteIV(ssl);
}
else {
key = wolfSSL_GetServerWriteKey(ssl);
iv = wolfSSL_GetServerWriteIV(ssl);
}
ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION);
if (ret != 0) {
printf("AesSetKey failed in myMacEncryptCb\n");
return ret;
}
encCtx->keySetup = 1;
}
/* encrypt */
ret = wc_AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz);
if (ret != 0)
return ret;
/* Reconstruct record header. */
wolfSSL_SetTlsHmacInner(ssl, myInner, encSz, content, macVerify);
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
if (ret != 0)
return ret;
ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl));
if (ret != 0)
return ret;
ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
if (ret != 0)
return ret;
ret = wc_HmacUpdate(&hmac, encOut, encSz);
if (ret != 0)
return ret;
return wc_HmacFinal(&hmac, macOut);
}
static WC_INLINE int myVerifyDecryptCb(WOLFSSL* ssl,
unsigned char* decOut, const unsigned char* decIn,
unsigned int decSz, int content, int macVerify,
unsigned int* padSz, void* ctx)
{
AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx;
int ret = 0;
int digestSz = wolfSSL_GetHmacSize(ssl);
Hmac hmac;
byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
byte verify[WC_MAX_DIGEST_SIZE];
const char* tlsStr = "TLS";
/* example supports (d)tls aes */
if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) {
printf("myMacEncryptCb not using AES\n");
return -1;
}
if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) {
printf("myMacEncryptCb not using (D)TLS\n");
return -1;
}
/* Reconstruct record header. */
wolfSSL_SetTlsHmacInner(ssl, myInner, decSz, content, macVerify);
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
if (ret != 0)
return ret;
ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
wolfSSL_GetMacSecret(ssl, macVerify), digestSz);
if (ret != 0)
return ret;
ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
if (ret != 0)
return ret;
ret = wc_HmacUpdate(&hmac, decIn, decSz);
if (ret != 0)
return ret;
ret = wc_HmacFinal(&hmac, verify);
if (ret != 0)
return ret;
if (XMEMCMP(verify, decOut + decSz, digestSz) != 0) {
printf("myDecryptVerify verify failed\n");
return -1;
}
/* decrypt */
if (decCtx->keySetup == 0) {
int keyLen = wolfSSL_GetKeySize(ssl);
const byte* key;
const byte* iv;
/* decrypt is from other side (peer) */
if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) {
key = wolfSSL_GetClientWriteKey(ssl);
iv = wolfSSL_GetClientWriteIV(ssl);
}
else {
key = wolfSSL_GetServerWriteKey(ssl);
iv = wolfSSL_GetServerWriteIV(ssl);
}
ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION);
if (ret != 0) {
printf("AesSetKey failed in myDecryptVerifyCb\n");
return ret;
}
decCtx->keySetup = 1;
}
/* decrypt */
ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz);
if (ret != 0)
return ret;
*padSz = *(decOut + decSz - 1) + 1;
return 0;
}
#endif
static WC_INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
{
@ -2179,6 +2341,14 @@ static WC_INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
wolfSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb);
wolfSSL_SetDecryptVerifyCtx(ssl, decCtx);
#if defined(HAVE_ENCRYPT_THEN_MAC)
wolfSSL_CTX_SetEncryptMacCb(ctx, myEncryptMacCb);
wolfSSL_SetEncryptMacCtx(ssl, encCtx);
wolfSSL_CTX_SetVerifyDecryptCb(ctx, myVerifyDecryptCb);
wolfSSL_SetVerifyDecryptCtx(ssl, decCtx);
#endif
}
@ -2187,6 +2357,8 @@ static WC_INLINE void FreeAtomicUser(WOLFSSL* ssl)
AtomicEncCtx* encCtx = (AtomicEncCtx*)wolfSSL_GetMacEncryptCtx(ssl);
AtomicDecCtx* decCtx = (AtomicDecCtx*)wolfSSL_GetDecryptVerifyCtx(ssl);
/* Encrypt-Then-MAC callbacks use same contexts. */
free(decCtx);
free(encCtx);
}