Merge pull request #4765 from haydenroche5/aes_siv

Add AES-SIV (RFC 5297).
This commit is contained in:
David Garske
2022-01-19 18:51:12 -08:00
committed by GitHub
12 changed files with 624 additions and 10 deletions

View File

@ -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)

View File

@ -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"

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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)

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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