mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-29 18:27:29 +02:00
Merge pull request #4765 from haydenroche5/aes_siv
Add AES-SIV (RFC 5297).
This commit is contained in:
@ -358,9 +358,32 @@ if(WOLFSSL_AESGCM)
|
||||
list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AESGCM")
|
||||
endif()
|
||||
|
||||
# AES-SIV
|
||||
set(WOLFSSL_AESSIV_HELP_STRING "Enable wolfSSL AES-SIV support (default: disabled)")
|
||||
add_option("WOLFSSL_AESSIV" ${WOLFSSL_AESSIV_HELP_STRING} "no" "yes;no")
|
||||
|
||||
if(WOLFSSL_AESSIV)
|
||||
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_AES_SIV")
|
||||
endif()
|
||||
|
||||
# AES-CTR
|
||||
set(WOLFSSL_AESCTR_HELP_STRING "Enable wolfSSL AES-CTR support (default: disabled)")
|
||||
add_option("WOLFSSL_AESCTR" ${WOLFSSL_AESCTR_HELP_STRING} "no" "yes;no")
|
||||
|
||||
if(WOLFSSL_OPENVPN OR
|
||||
WOLFSSL_LIBSSH2 OR
|
||||
WOLFSSL_AESSIV)
|
||||
override_cache(WOLFSSL_AESCTR "yes")
|
||||
endif()
|
||||
|
||||
if(WOLFSSL_AESCTR AND NOT WOLFSSL_FORTRESS)
|
||||
list(APPEND WOLFSSL_DEFINITIONS
|
||||
"-DWOLFSSL_AES_COUNTER"
|
||||
"-DWOLFSSL_AES_DIRECT")
|
||||
endif()
|
||||
|
||||
# TODO: - AES-CCM
|
||||
# - AES-GCM stream
|
||||
# - AES-CTR
|
||||
# - AES-OFB
|
||||
# - AES-CFB
|
||||
# - AES-ARM
|
||||
@ -623,7 +646,7 @@ add_option("WOLFSSL_ERROR_STRINGS" ${WOLFSSL_ERROR_STRINGS_HELP_STRING} "yes" "y
|
||||
if(NOT WOLFSSL_ERROR_STRINGS)
|
||||
list(APPEND WOLFSSL_DEFINITIONS "-DNO_ERROR_STRINGS")
|
||||
else()
|
||||
# turn off error strings if leanpsk or leantls o
|
||||
# turn off error strings if leanpsk or leantls on
|
||||
if(WOLFSSL_LEAN_PSK OR WOLFSSL_LEAN_TLS)
|
||||
list(APPEND WOLFSSL_DEFINITIONS "-DNO_ERROR_STRINGS")
|
||||
override_cache(WOLFSSL_ERROR_STRINGS "no")
|
||||
@ -897,10 +920,27 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO: - CMAC
|
||||
# - AES-XTS
|
||||
# TODO: - AES-XTS
|
||||
# - Web server
|
||||
# - Web client
|
||||
set(WOLFSSL_CMAC_HELP_STRING "Enable CMAC (default: disabled)")
|
||||
add_option("WOLFSSL_CMAC" ${WOLFSSL_CMAC_HELP_STRING} "no" "yes;no")
|
||||
|
||||
if(WOLFSSL_WPAS OR
|
||||
WOLFSSL_NTP OR
|
||||
WOLFSSL_AESSIV)
|
||||
override_cache(WOLFSSL_CMAC "yes")
|
||||
endif()
|
||||
|
||||
if(WOLFSSL_CMAC)
|
||||
if (NOT WOLFSSL_AES)
|
||||
message(FATAL_ERROR "Cannot use CMAC without AES.")
|
||||
else()
|
||||
list(APPEND WOLFSSL_DEFINITIONS
|
||||
"-DWOLFSSL_CMAC"
|
||||
"-DWOLFSSL_AES_DIRECT")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# RABBIT
|
||||
if(NOT WOLFSSL_RABBIT)
|
||||
|
15
configure.ac
15
configure.ac
@ -498,6 +498,7 @@ then
|
||||
test "$enable_aesctr" = "" && enable_aesctr=yes
|
||||
test "$enable_aesofb" = "" && enable_aesofb=yes
|
||||
test "$enable_aescfb" = "" && enable_aescfb=yes
|
||||
test "$enable_aessiv" = "" && enable_aessiv=yes
|
||||
test "$enable_aescbc_length_checks" = "" && enable_aescbc_length_checks=yes
|
||||
test "$enable_camellia" = "" && enable_camellia=yes
|
||||
test "$enable_ripemd" = "" && enable_ripemd=yes
|
||||
@ -664,6 +665,7 @@ then
|
||||
test "$enable_aesctr" = "" && enable_aesctr=yes
|
||||
test "$enable_aesofb" = "" && enable_aesofb=yes
|
||||
test "$enable_aescfb" = "" && enable_aescfb=yes
|
||||
test "$enable_aessiv" = "" && enable_aessiv=yes
|
||||
test "$enable_aescbc_length_checks" = "" && enable_aescbc_length_checks=yes
|
||||
test "$enable_camellia" = "" && enable_camellia=yes
|
||||
test "$enable_ripemd" = "" && enable_ripemd=yes
|
||||
@ -1588,6 +1590,12 @@ then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM"
|
||||
fi
|
||||
|
||||
# AES-SIV (RFC 5297)
|
||||
AC_ARG_ENABLE([aessiv],
|
||||
[AS_HELP_STRING([--enable-aessiv],[Enable AES-SIV (RFC 5297) (default: disabled)])],
|
||||
[ ENABLED_AESSIV=$enableval ],
|
||||
[ ENABLED_AESSIV=no ]
|
||||
)
|
||||
|
||||
# AES-CTR
|
||||
AC_ARG_ENABLE([aesctr],
|
||||
@ -1595,7 +1603,7 @@ AC_ARG_ENABLE([aesctr],
|
||||
[ ENABLED_AESCTR=$enableval ],
|
||||
[ ENABLED_AESCTR=no ]
|
||||
)
|
||||
if test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_LIBSSH2" = "yes"
|
||||
if test "$ENABLED_OPENVPN" = "yes" || test "$ENABLED_LIBSSH2" = "yes" || test "$ENABLED_AESSIV" = "yes"
|
||||
then
|
||||
ENABLED_AESCTR=yes
|
||||
fi
|
||||
@ -3359,7 +3367,7 @@ AC_ARG_ENABLE([cmac],
|
||||
[ ENABLED_CMAC=no ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_WPAS" != "no" || test "$ENABLED_NTP" = "yes"
|
||||
if test "$ENABLED_WPAS" != "no" || test "$ENABLED_NTP" = "yes" || test "$ENABLED_AESSIV" = "yes"
|
||||
then
|
||||
ENABLED_CMAC=yes
|
||||
fi
|
||||
@ -6948,6 +6956,8 @@ fi
|
||||
AS_IF([test "x$ENABLED_OPENSSLALL" = "xyes"],
|
||||
[AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT"])
|
||||
|
||||
AS_IF([test "x$ENABLED_AESSIV" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_SIV"])
|
||||
|
||||
AS_IF([test "x$ENABLED_AESCTR" = "xyes" && test "x$ENABLED_FORTRESS" != "xyes"],
|
||||
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER -DWOLFSSL_AES_DIRECT"])
|
||||
|
||||
@ -7679,6 +7689,7 @@ echo " * AES-CCM: $ENABLED_AESCCM"
|
||||
echo " * AES-CTR: $ENABLED_AESCTR"
|
||||
echo " * AES-CFB: $ENABLED_AESCFB"
|
||||
echo " * AES-OFB: $ENABLED_AESOFB"
|
||||
echo " * AES-SIV: $ENABLED_AESSIV"
|
||||
echo " * DES3: $ENABLED_DES3"
|
||||
echo " * IDEA: $ENABLED_IDEA"
|
||||
echo " * Camellia: $ENABLED_CAMELLIA"
|
||||
|
@ -934,3 +934,97 @@ WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
||||
\sa wc_AesSetKey
|
||||
*/
|
||||
WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
|
||||
\brief This function performs SIV (synthetic initialization vector)
|
||||
encryption as described in RFC 5297.
|
||||
|
||||
\return 0 On successful encryption.
|
||||
\return BAD_FUNC_ARG If key, SIV, or output buffer are NULL. Also returned
|
||||
if the key size isn't 32, 48, or 64 bytes.
|
||||
\return Other Other negative error values returned if AES or CMAC operations
|
||||
fail.
|
||||
|
||||
\param key Byte buffer containing the key to use.
|
||||
\param keySz Length of the key buffer in bytes.
|
||||
\param assoc Additional, authenticated associated data (AD).
|
||||
\param assocSz Length of AD buffer in bytes.
|
||||
\param nonce A number used once. Used by the algorithm in the same manner as
|
||||
the AD.
|
||||
\param nonceSz Length of nonce buffer in bytes.
|
||||
\param in Plaintext buffer to encrypt.
|
||||
\param inSz Length of plaintext buffer.
|
||||
\param siv The SIV output by S2V (see RFC 5297 2.4).
|
||||
\param out Buffer to hold the ciphertext. Should be the same length as the
|
||||
plaintext buffer.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
byte key[] = { some 32, 48, or 64 byte key };
|
||||
byte assoc[] = {0x01, 0x2, 0x3};
|
||||
byte nonce[] = {0x04, 0x5, 0x6};
|
||||
byte plainText[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
byte siv[AES_BLOCK_SIZE];
|
||||
byte cipherText[sizeof(plainText)];
|
||||
if (wc_AesSivEncrypt(key, sizeof(key), assoc, sizeof(assoc), nonce,
|
||||
sizeof(nonce), plainText, sizeof(plainText), siv, cipherText) != 0) {
|
||||
// failed to encrypt
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa wc_AesSivDecrypt
|
||||
*/
|
||||
|
||||
WOLFSSL_API
|
||||
int wc_AesSivEncrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out);
|
||||
|
||||
/*!
|
||||
\ingroup AES
|
||||
\brief This function performs SIV (synthetic initialization vector)
|
||||
decryption as described in RFC 5297.
|
||||
|
||||
\return 0 On successful decryption.
|
||||
\return BAD_FUNC_ARG If key, SIV, or output buffer are NULL. Also returned
|
||||
if the key size isn't 32, 48, or 64 bytes.
|
||||
\return AES_SIV_AUTH_E If the SIV derived by S2V doesn't match the input
|
||||
SIV (see RFC 5297 2.7).
|
||||
\return Other Other negative error values returned if AES or CMAC operations
|
||||
fail.
|
||||
|
||||
\param key Byte buffer containing the key to use.
|
||||
\param keySz Length of the key buffer in bytes.
|
||||
\param assoc Additional, authenticated associated data (AD).
|
||||
\param assocSz Length of AD buffer in bytes.
|
||||
\param nonce A number used once. Used by the underlying algorithm in the
|
||||
same manner as the AD.
|
||||
\param nonceSz Length of nonce buffer in bytes.
|
||||
\param in Ciphertext buffer to decrypt.
|
||||
\param inSz Length of ciphertext buffer.
|
||||
\param siv The SIV that accompanies the ciphertext (see RFC 5297 2.4).
|
||||
\param out Buffer to hold the decrypted plaintext. Should be the same length
|
||||
as the ciphertext buffer.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
byte key[] = { some 32, 48, or 64 byte key };
|
||||
byte assoc[] = {0x01, 0x2, 0x3};
|
||||
byte nonce[] = {0x04, 0x5, 0x6};
|
||||
byte cipherText[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
byte siv[AES_BLOCK_SIZE] = { the SIV that came with the ciphertext };
|
||||
byte plainText[sizeof(cipherText)];
|
||||
if (wc_AesSivDecrypt(key, sizeof(key), assoc, sizeof(assoc), nonce,
|
||||
sizeof(nonce), cipherText, sizeof(cipherText), siv, plainText) != 0) {
|
||||
// failed to decrypt
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa wc_AesSivEncrypt
|
||||
*/
|
||||
WOLFSSL_API
|
||||
int wc_AesSivDecrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out);
|
||||
|
@ -282,6 +282,7 @@
|
||||
#define BENCH_IDEA 0x00008000
|
||||
#define BENCH_AES_CFB 0x00010000
|
||||
#define BENCH_AES_OFB 0x00020000
|
||||
#define BENCH_AES_SIV 0x00040000
|
||||
/* Digest algorithms. */
|
||||
#define BENCH_MD5 0x00000001
|
||||
#define BENCH_POLY1305 0x00000002
|
||||
@ -434,6 +435,9 @@ static const bench_alg bench_cipher_opt[] = {
|
||||
#ifdef HAVE_AESCCM
|
||||
{ "-aes-ccm", BENCH_AES_CCM },
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
{ "-aes-siv", BENCH_AES_SIV },
|
||||
#endif
|
||||
#ifdef HAVE_CAMELLIA
|
||||
{ "-camellia", BENCH_CAMELLIA },
|
||||
#endif
|
||||
@ -1135,7 +1139,11 @@ static const XGEN_ALIGN byte bench_key_buf[] =
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
||||
0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10,
|
||||
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67,
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
|
||||
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
|
||||
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
|
||||
0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
|
||||
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
|
||||
};
|
||||
|
||||
static const XGEN_ALIGN byte bench_iv_buf[] =
|
||||
@ -1730,6 +1738,10 @@ static void* benchmarks_do(void* args)
|
||||
if (bench_all || (bench_cipher_algs & BENCH_AES_CCM))
|
||||
bench_aesccm();
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
if (bench_all || (bench_cipher_algs & BENCH_AES_SIV))
|
||||
bench_aessiv();
|
||||
#endif
|
||||
#endif /* !NO_AES */
|
||||
|
||||
#ifdef HAVE_CAMELLIA
|
||||
@ -3162,6 +3174,58 @@ void bench_aesccm(void)
|
||||
WC_FREE_VAR(bench_tag, HEAP_HINT);
|
||||
}
|
||||
#endif /* HAVE_AESCCM */
|
||||
|
||||
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
static void bench_aessiv_internal(const byte* key, word32 keySz, const char*
|
||||
encLabel, const char* decLabel)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
byte assoc[AES_BLOCK_SIZE];
|
||||
byte nonce[AES_BLOCK_SIZE];
|
||||
byte siv[AES_BLOCK_SIZE];
|
||||
int count = 0;
|
||||
double start;
|
||||
|
||||
bench_stats_start(&count, &start);
|
||||
do {
|
||||
for (i = 0; i < numBlocks; i++) {
|
||||
ret = wc_AesSivEncrypt(key, keySz, assoc, AES_BLOCK_SIZE, nonce,
|
||||
AES_BLOCK_SIZE, bench_plain, bench_size,
|
||||
siv, bench_cipher);
|
||||
if (ret != 0) {
|
||||
printf("wc_AesSivEncrypt failed (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
count += i;
|
||||
} while (bench_stats_sym_check(start));
|
||||
bench_stats_sym_finish(encLabel, 0, count, bench_size, start, ret);
|
||||
|
||||
bench_stats_start(&count, &start);
|
||||
do {
|
||||
for (i = 0; i < numBlocks; i++) {
|
||||
ret = wc_AesSivDecrypt(key, keySz, assoc, AES_BLOCK_SIZE, nonce,
|
||||
AES_BLOCK_SIZE, bench_cipher, bench_size,
|
||||
siv, bench_plain);
|
||||
if (ret != 0) {
|
||||
printf("wc_AesSivDecrypt failed (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
count += i;
|
||||
} while (bench_stats_sym_check(start));
|
||||
bench_stats_sym_finish(decLabel, 0, count, bench_size, start, ret);
|
||||
}
|
||||
|
||||
void bench_aessiv(void)
|
||||
{
|
||||
bench_aessiv_internal(bench_key, 32, "AES-256-SIV-enc", "AES-256-SIV-dec");
|
||||
bench_aessiv_internal(bench_key, 48, "AES-384-SIV-enc", "AES-384-SIV-dec");
|
||||
bench_aessiv_internal(bench_key, 64, "AES-512-SIV-enc", "AES-512-SIV-dec");
|
||||
}
|
||||
#endif /* WOLFSSL_AES_SIV */
|
||||
#endif /* !NO_AES */
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ void bench_aesxts(void);
|
||||
void bench_aesctr(void);
|
||||
void bench_aescfb(void);
|
||||
void bench_aesofb(void);
|
||||
void bench_aessiv(void);
|
||||
void bench_poly1305(void);
|
||||
void bench_camellia(void);
|
||||
void bench_md5(int);
|
||||
|
@ -72,6 +72,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
|
||||
#include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
#include <wolfssl/wolfcrypt/cmac.h>
|
||||
#endif
|
||||
|
||||
/* fips wrapper calls, user can call direct */
|
||||
#if defined(HAVE_FIPS) && \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
|
||||
@ -11684,5 +11688,231 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
||||
|
||||
#endif /* WOLFSSL_AES_XTS */
|
||||
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
|
||||
/*
|
||||
* See RFC 5297 Section 2.4.
|
||||
*/
|
||||
static int S2V(const byte* key, word32 keySz, const byte* assoc, word32 assocSz,
|
||||
const byte* nonce, word32 nonceSz, const byte* data,
|
||||
word32 dataSz, byte* out)
|
||||
{
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
byte* tmp[3] = {NULL, NULL, NULL};
|
||||
int i;
|
||||
Cmac* cmac;
|
||||
#else
|
||||
byte tmp[3][AES_BLOCK_SIZE];
|
||||
Cmac cmac[1];
|
||||
#endif
|
||||
word32 macSz = AES_BLOCK_SIZE;
|
||||
int ret = 0;
|
||||
word32 zeroBytes;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
for (i = 0; i < 3; ++i) {
|
||||
tmp[i] = (byte*)XMALLOC(AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (tmp[i] == NULL) {
|
||||
ret = MEMORY_E;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret == 0)
|
||||
#endif
|
||||
{
|
||||
XMEMSET(tmp[1], 0, AES_BLOCK_SIZE);
|
||||
XMEMSET(tmp[2], 0, AES_BLOCK_SIZE);
|
||||
|
||||
ret = wc_AesCmacGenerate(tmp[0], &macSz, tmp[1], AES_BLOCK_SIZE,
|
||||
key, keySz);
|
||||
if (ret == 0) {
|
||||
ShiftAndXorRb(tmp[1], tmp[0]);
|
||||
ret = wc_AesCmacGenerate(tmp[0], &macSz, assoc, assocSz, key,
|
||||
keySz);
|
||||
if (ret == 0) {
|
||||
xorbuf(tmp[1], tmp[0], AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ShiftAndXorRb(tmp[0], tmp[1]);
|
||||
ret = wc_AesCmacGenerate(tmp[1], &macSz, nonce, nonceSz, key, keySz);
|
||||
if (ret == 0) {
|
||||
xorbuf(tmp[0], tmp[1], AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (dataSz >= AES_BLOCK_SIZE) {
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
cmac = (Cmac*)XMALLOC(sizeof(Cmac), NULL, DYNAMIC_TYPE_CMAC);
|
||||
if (cmac == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
if (ret == 0)
|
||||
#endif
|
||||
{
|
||||
xorbuf(tmp[0], data + (dataSz - AES_BLOCK_SIZE),
|
||||
AES_BLOCK_SIZE);
|
||||
ret = wc_InitCmac(cmac, key, keySz, WC_CMAC_AES, NULL);
|
||||
if (ret == 0) {
|
||||
ret = wc_CmacUpdate(cmac, data, dataSz - AES_BLOCK_SIZE);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CmacUpdate(cmac, tmp[0], AES_BLOCK_SIZE);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CmacFinal(cmac, out, &macSz);
|
||||
}
|
||||
}
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
if (cmac != NULL) {
|
||||
XFREE(cmac, NULL, DYNAMIC_TYPE_CMAC);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
XMEMCPY(tmp[2], data, dataSz);
|
||||
tmp[2][dataSz] |= 0x80;
|
||||
zeroBytes = AES_BLOCK_SIZE - (dataSz + 1);
|
||||
if (zeroBytes != 0) {
|
||||
XMEMSET(tmp[2] + dataSz + 1, 0, zeroBytes);
|
||||
}
|
||||
ShiftAndXorRb(tmp[1], tmp[0]);
|
||||
xorbuf(tmp[1], tmp[2], AES_BLOCK_SIZE);
|
||||
ret = wc_AesCmacGenerate(out, &macSz, tmp[1], AES_BLOCK_SIZE, key,
|
||||
keySz);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (tmp[i] != NULL) {
|
||||
XFREE(tmp[i], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int AesSivCipher(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* data, word32 dataSz, byte* siv, byte* out,
|
||||
int enc)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
Aes* aes = NULL;
|
||||
#else
|
||||
Aes aes[1];
|
||||
#endif
|
||||
byte sivTmp[AES_BLOCK_SIZE];
|
||||
|
||||
if (key == NULL || siv == NULL || out == NULL) {
|
||||
WOLFSSL_MSG("Bad parameter");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0 && keySz != 32 && keySz != 48 && keySz != 64) {
|
||||
WOLFSSL_MSG("Bad key size. Must be 256, 384, or 512 bits.");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
if (ret == 0) {
|
||||
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_AES);
|
||||
if (aes == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0) {
|
||||
if (enc == 1) {
|
||||
ret = S2V(key, keySz / 2, assoc, assocSz, nonce, nonceSz, data,
|
||||
dataSz, sivTmp);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("S2V failed.");
|
||||
}
|
||||
else {
|
||||
XMEMCPY(siv, sivTmp, AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
XMEMCPY(sivTmp, siv, AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("Failed to initialized AES object.");
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0 && dataSz > 0) {
|
||||
sivTmp[12] &= 0x7f;
|
||||
sivTmp[8] &= 0x7f;
|
||||
ret = wc_AesSetKey(aes, key + keySz / 2, keySz / 2, sivTmp,
|
||||
AES_ENCRYPTION);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("Failed to set key for AES-CTR.");
|
||||
}
|
||||
else {
|
||||
ret = wc_AesCtrEncrypt(aes, out, data, dataSz);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("AES-CTR encryption failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0 && enc == 0) {
|
||||
ret = S2V(key, keySz / 2, assoc, assocSz, nonce, nonceSz, out, dataSz,
|
||||
sivTmp);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("S2V failed.");
|
||||
}
|
||||
|
||||
if (XMEMCMP(siv, sivTmp, AES_BLOCK_SIZE) != 0) {
|
||||
WOLFSSL_MSG("Computed SIV doesn't match received SIV.");
|
||||
ret = AES_SIV_AUTH_E;
|
||||
}
|
||||
}
|
||||
|
||||
wc_AesFree(aes);
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* See RFC 5297 Section 2.6.
|
||||
*/
|
||||
int wc_AesSivEncrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out)
|
||||
{
|
||||
return AesSivCipher(key, keySz, assoc, assocSz, nonce, nonceSz, in, inSz,
|
||||
siv, out, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* See RFC 5297 Section 2.7.
|
||||
*/
|
||||
int wc_AesSivDecrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out)
|
||||
{
|
||||
return AesSivCipher(key, keySz, assoc, assocSz, nonce, nonceSz, in, inSz,
|
||||
siv, out, 0);
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_AES_SIV */
|
||||
|
||||
#endif /* HAVE_FIPS */
|
||||
#endif /* !NO_AES */
|
||||
|
@ -57,7 +57,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FIPS
|
||||
static void ShiftAndXorRb(byte* out, byte* in)
|
||||
#else
|
||||
/* Used by AES-SIV. See aes.c. */
|
||||
void ShiftAndXorRb(byte* out, byte* in)
|
||||
#endif
|
||||
{
|
||||
int i, j, xorRb;
|
||||
int mask = 0, last = 0;
|
||||
@ -76,8 +81,6 @@ static void ShiftAndXorRb(byte* out, byte* in)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns 0 on success */
|
||||
int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz,
|
||||
int type, void* unused, void* heap, int devId)
|
||||
|
@ -230,6 +230,9 @@ const char* wc_GetErrorString(int error)
|
||||
case AES_CCM_AUTH_E:
|
||||
return "AES-CCM Authentication check fail";
|
||||
|
||||
case AES_SIV_AUTH_E:
|
||||
return "AES-SIV authentication failure";
|
||||
|
||||
case ASYNC_INIT_E:
|
||||
return "Async Init error";
|
||||
|
||||
|
@ -556,6 +556,9 @@ WOLFSSL_TEST_SUBROUTINE int cryptocb_test(void);
|
||||
#ifdef WOLFSSL_CERT_PIV
|
||||
WOLFSSL_TEST_SUBROUTINE int certpiv_test(void);
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
WOLFSSL_TEST_SUBROUTINE int aes_siv_test(void);
|
||||
#endif
|
||||
|
||||
/* General big buffer size for many tests. */
|
||||
#define FOURK_BUF 4096
|
||||
@ -1142,6 +1145,12 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
||||
else
|
||||
TEST_PASS("AES Key Wrap test passed!\n");
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
if ( (ret = aes_siv_test()) != 0)
|
||||
return err_sys("AES-SIV test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("AES-SIV test passed!\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CAMELLIA
|
||||
@ -38526,6 +38535,148 @@ WOLFSSL_TEST_SUBROUTINE int time_test(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
|
||||
typedef struct {
|
||||
const byte key[32];
|
||||
word32 keySz;
|
||||
const byte nonce[48];
|
||||
word32 nonceSz;
|
||||
const byte assoc[80];
|
||||
word32 assocSz;
|
||||
const byte plaintext[82];
|
||||
word32 plaintextSz;
|
||||
const byte siv[AES_BLOCK_SIZE];
|
||||
const byte ciphertext[82];
|
||||
word32 ciphertextSz;
|
||||
} AesSivTestVector;
|
||||
|
||||
#define AES_SIV_TEST_VECTORS 7
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE int aes_siv_test(void)
|
||||
{
|
||||
/* These test vectors come from chrony 4.1's SIV unit tests. */
|
||||
WOLFSSL_SMALL_STACK_STATIC const AesSivTestVector testVectors[AES_SIV_TEST_VECTORS] = {
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", 16,
|
||||
"", 0,
|
||||
"", 0,
|
||||
"\x22\x3e\xb5\x94\xe0\xe0\x25\x4b\x00\x25\x8e\x21\x9a\x1c\xa4\x21",
|
||||
"", 0
|
||||
},
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", 16,
|
||||
"\x4c\x9d\x4f\xca\xed\x8a\xe2\xba\xad\x3f\x3e\xa6\xe9\x3c\x8c\x8b", 16,
|
||||
"", 0,
|
||||
"\xd7\x20\x19\x89\xc6\xdb\xc6\xd6\x61\xfc\x62\xbc\x86\x5e\xee\xef",
|
||||
"", 0
|
||||
},
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", 16,
|
||||
"", 0,
|
||||
"\x4c\x9d\x4f\xca\xed\x8a\xe2\xba\xad\x3f\x3e\xa6\xe9\x3c\x8c\x8b", 16,
|
||||
"\xb6\xc1\x60\xe9\xc2\xfd\x2a\xe8\xde\xc5\x36\x8b\x2a\x33\xed\xe1",
|
||||
"\x14\xff\xb3\x97\x34\x5c\xcb\xe4\x4a\xa4\xde\xac\xd9\x36\x90\x46", 16
|
||||
},
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e", 15,
|
||||
"\x4c\x9d\x4f\xca\xed\x8a\xe2\xba\xad\x3f\x3e\xa6\xe9\x3c\x8c", 15,
|
||||
"\xba\x99\x79\x31\x23\x7e\x3c\x53\x58\x7e\xd4\x93\x02\xab\xe4", 15,
|
||||
"\x03\x8c\x41\x51\xba\x7a\x8f\x77\x6e\x56\x31\x99\x42\x0b\xc7\x03",
|
||||
"\xe7\x6c\x67\xc9\xda\xb7\x0d\x5b\x44\x06\x26\x5a\xd0\xd2\x3b", 15
|
||||
},
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", 16,
|
||||
"\x4c\x9d\x4f\xca\xed\x8a\xe2\xba\xad\x3f\x3e\xa6\xe9\x3c\x8c\x8b", 16,
|
||||
"\xba\x99\x79\x31\x23\x7e\x3c\x53\x58\x7e\xd4\x93\x02\xab\xe4\xa7", 16,
|
||||
"\x5c\x05\x23\x65\xf4\x57\x0a\xa0\xfb\x38\x3e\xce\x9b\x75\x85\xeb",
|
||||
"\x68\x85\x19\x36\x0c\x7c\x48\x11\x40\xcb\x9b\x57\x9a\x0e\x65\x32", 16
|
||||
},
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
|
||||
"\xd5", 17,
|
||||
"\x4c\x9d\x4f\xca\xed\x8a\xe2\xba\xad\x3f\x3e\xa6\xe9\x3c\x8c\x8b"
|
||||
"\xa0", 17,
|
||||
"\xba\x99\x79\x31\x23\x7e\x3c\x53\x58\x7e\xd4\x93\x02\xab\xe4\xa7"
|
||||
"\x08", 17,
|
||||
"\xaf\x58\x4b\xe7\x82\x1e\x96\x19\x29\x91\x25\xe0\xdd\x80\x3b\x49",
|
||||
"\xa5\x11\xcd\xb6\x08\xf3\x76\xa0\xb6\xfa\x15\x82\xf3\x95\xe1\xeb"
|
||||
"\xbd", 17
|
||||
},
|
||||
{ "\x01\x23\x45\x67\x89\xab\xcd\xef\xf0\x12\x34\x56\x78\x9a\xbc\xde"
|
||||
"\xef\x01\x23\x45\x67\x89\xab\xcd\xde\xf0\x12\x34\x56\x78\x9a\xbc", 32,
|
||||
"\xb0\x5a\x1b\xc7\x56\xe7\xb6\x2c\xb4\x85\xe5\x56\xa5\x28\xc0\x6c"
|
||||
"\x2f\x3b\x0b\x9d\x1a\x0c\xdf\x69\x47\xe0\xcc\xc0\x87\xaa\x5c\x09"
|
||||
"\x98\x48\x8d\x6a\x8e\x1e\x05\xd7\x8b\x68\x74\x83\xb5\x1d\xf1\x2c", 48,
|
||||
"\xe5\x8b\xd2\x6a\x30\xc5\xc5\x61\xcc\xbd\x7c\x27\xbf\xfe\xf9\x06"
|
||||
"\x00\x5b\xd7\xfc\x11\x0b\xcf\x16\x61\xef\xac\x05\xa7\xaf\xec\x27"
|
||||
"\x41\xc8\x5e\x9e\x0d\xf9\x2f\xaf\x20\x79\x17\xe5\x17\x91\x2a\x27"
|
||||
"\x34\x1c\xbc\xaf\xeb\xef\x7f\x52\xe7\x1e\x4c\x2a\xca\xbd\x2b\xbe"
|
||||
"\x34\xd6\xfb\x69\xd3\x3e\x49\x59\x60\xb4\x26\xc9\xb8\xce\xba", 79,
|
||||
"\x6c\xe7\xcf\x7e\xab\x7b\xa0\xe1\xa7\x22\xcb\x88\xde\x5e\x42\xd2"
|
||||
"\xec\x79\xe0\xa2\xcf\x5f\x0f\x6f\x6b\x89\x57\xcd\xae\x17\xd4\xc2"
|
||||
"\xf3\x1b\xa2\xa8\x13\x78\x23\x2f\x83\xa8\xd4\x0c\xc0\xd2\xf3\x99"
|
||||
"\xae\x81\xa1\xca\x5b\x5f\x45\xa6\x6f\x0c\x8a\xf3\xd4\x67\x40\x81"
|
||||
"\x26\xe2\x01\x86\xe8\x5a\xd5\xf8\x58\x80\x9f\x56\xaa\x76\x96\xbf"
|
||||
"\x31", 81,
|
||||
"\x9a\x06\x33\xe0\xee\x00\x6a\x9b\xc8\x20\xd5\xe2\xc2\xed\xb5\x75",
|
||||
"\xfa\x9e\x42\x2a\x31\x6b\xda\xca\xaa\x7d\x31\x8b\x84\x7a\xb8\xd7"
|
||||
"\x8a\x81\x25\x64\xed\x41\x9b\xa9\x77\x10\xbd\x05\x0c\x4e\xc5\x31"
|
||||
"\x0c\xa2\x86\xec\x8a\x94\xc8\x24\x23\x3c\x13\xee\xa5\x51\xc9\xdf"
|
||||
"\x48\xc9\x55\xc5\x2f\x40\x73\x3f\x98\xbb\x8d\x69\x78\x46\x64\x17"
|
||||
"\x8d\x49\x2f\x14\x62\xa4\x7c\x2a\x57\x38\x87\xce\xc6\x72\xd3\x5c"
|
||||
"\xa1", 81
|
||||
}};
|
||||
int i;
|
||||
byte computedCiphertext[82];
|
||||
byte computedPlaintext[82];
|
||||
byte siv[AES_BLOCK_SIZE];
|
||||
int rc = 0;
|
||||
|
||||
for (i = 0; i < AES_SIV_TEST_VECTORS; ++i) {
|
||||
rc = wc_AesSivEncrypt(testVectors[i].key, testVectors[i].keySz,
|
||||
testVectors[i].assoc, testVectors[i].assocSz,
|
||||
testVectors[i].nonce, testVectors[i].nonceSz,
|
||||
testVectors[i].plaintext,
|
||||
testVectors[i].plaintextSz, siv,
|
||||
computedCiphertext);
|
||||
if (rc != 0) {
|
||||
return -16000;
|
||||
}
|
||||
rc = XMEMCMP(siv, testVectors[i].siv, AES_BLOCK_SIZE);
|
||||
if (rc != 0) {
|
||||
return -16001;
|
||||
}
|
||||
rc = XMEMCMP(computedCiphertext, testVectors[i].ciphertext,
|
||||
testVectors[i].ciphertextSz);
|
||||
if (rc != 0) {
|
||||
return -16002;
|
||||
}
|
||||
rc = wc_AesSivDecrypt(testVectors[i].key, testVectors[i].keySz,
|
||||
testVectors[i].assoc, testVectors[i].assocSz,
|
||||
testVectors[i].nonce, testVectors[i].nonceSz,
|
||||
computedCiphertext, testVectors[i].plaintextSz,
|
||||
siv, computedPlaintext);
|
||||
if (rc != 0) {
|
||||
return -16003;
|
||||
}
|
||||
rc = XMEMCMP(computedPlaintext, testVectors[i].plaintext,
|
||||
testVectors[i].plaintextSz);
|
||||
if (rc != 0) {
|
||||
return -16004;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef ERROR_OUT
|
||||
|
||||
#else
|
||||
|
@ -523,6 +523,17 @@ WOLFSSL_API int wc_AesInit_Label(Aes* aes, const char* label, void* heap,
|
||||
#endif
|
||||
WOLFSSL_API void wc_AesFree(Aes* aes);
|
||||
|
||||
#ifdef WOLFSSL_AES_SIV
|
||||
WOLFSSL_API
|
||||
int wc_AesSivEncrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out);
|
||||
WOLFSSL_API
|
||||
int wc_AesSivDecrypt(const byte* key, word32 keySz, const byte* assoc,
|
||||
word32 assocSz, const byte* nonce, word32 nonceSz,
|
||||
const byte* in, word32 inSz, byte* siv, byte* out);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@ -103,6 +103,11 @@ int wc_AesCmacVerify(const byte* check, word32 checkSz,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* key, word32 keySz);
|
||||
|
||||
#ifndef HAVE_FIPS
|
||||
WOLFSSL_LOCAL
|
||||
void ShiftAndXorRb(byte* out, byte* in);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@ -247,8 +247,9 @@ enum {
|
||||
ECC_PCT_E = -286, /* ECDHE Pairwise Consistency Test failure */
|
||||
FIPS_PRIVATE_KEY_LOCKED_E = -287, /* Cannot export private key. */
|
||||
PROTOCOLCB_UNAVAILABLE = -288, /* Protocol callback unavailable */
|
||||
AES_SIV_AUTH_E = -289, /* AES-SIV authentication failed */
|
||||
|
||||
WC_LAST_E = -288, /* Update this to indicate last error */
|
||||
WC_LAST_E = -289, /* Update this to indicate last error */
|
||||
MIN_CODE_E = -300 /* errors -101 - -299 */
|
||||
|
||||
/* add new companion error id strings for any new error codes
|
||||
|
Reference in New Issue
Block a user