mirror of https://github.com/wolfSSL/wolfssl.git
Implement AES-CTS in wolfCrypt
parent
6761dbb2ed
commit
75ca54889c
16
configure.ac
16
configure.ac
|
@ -5438,6 +5438,22 @@ AC_ARG_ENABLE([xts],
|
|||
[ ENABLED_AESXTS=$enableval ]
|
||||
)
|
||||
|
||||
# AES-CTS
|
||||
AC_ARG_ENABLE([aescts],
|
||||
[AS_HELP_STRING([--enable-aescts],[Enable AES CTS (default: disabled)])],
|
||||
[ ENABLED_AESCTS=$enableval ],
|
||||
[ ENABLED_AESCTS=no ]
|
||||
)
|
||||
|
||||
if test "$ENABLED_AESCTS" = "yes"
|
||||
then
|
||||
if test "$ENABLED_AESCBC" = "no"
|
||||
then
|
||||
AC_MSG_ERROR([AES CTS requires AES CBC.])
|
||||
fi
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_CTS"
|
||||
fi
|
||||
|
||||
# Web Server Build
|
||||
AC_ARG_ENABLE([webserver],
|
||||
[AS_HELP_STRING([--enable-webserver],[Enable Web Server (default: disabled)])],
|
||||
|
|
|
@ -263,6 +263,230 @@ int test_wc_AesCbcEncryptDecrypt(void)
|
|||
return EXPECT_RESULT();
|
||||
} /* END test_wc_AesCbcEncryptDecrypt */
|
||||
|
||||
/*******************************************************************************
|
||||
* AES-CTS
|
||||
******************************************************************************/
|
||||
|
||||
int test_wc_AesCtsEncryptDecrypt(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(NO_AES) && defined(WOLFSSL_AES_CTS) && \
|
||||
defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_128)
|
||||
/* Test vectors taken form RFC3962 Appendix B */
|
||||
struct {
|
||||
const char* input;
|
||||
const char* output;
|
||||
size_t inLen;
|
||||
size_t outLen;
|
||||
} vects[] = {
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20",
|
||||
"\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
|
||||
"\x97",
|
||||
17, 17
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20",
|
||||
"\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5",
|
||||
31, 31
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43",
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
|
||||
32, 32
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
|
||||
"\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c",
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
|
||||
"\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5",
|
||||
47, 47
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
|
||||
"\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20",
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
|
||||
"\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
|
||||
48, 48
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
|
||||
"\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
|
||||
"\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
|
||||
"\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
|
||||
"\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
|
||||
64, 64
|
||||
}
|
||||
};
|
||||
byte keyBytes[AES_128_KEY_SIZE] = {
|
||||
0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
|
||||
0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69
|
||||
};
|
||||
byte tmp[64]; /* Largest vector size */
|
||||
size_t i;
|
||||
byte iv[AES_IV_SIZE]; /* All-zero IV for all cases */
|
||||
|
||||
XMEMSET(iv, 0, sizeof(iv));
|
||||
for (i = 0; i < XELEM_CNT(vects) && EXPECT_SUCCESS(); i++) {
|
||||
/* One-shot encrypt */
|
||||
XMEMSET(tmp, 0, sizeof(tmp));
|
||||
ExpectIntEQ(wc_AesCtsEncrypt(keyBytes, sizeof(keyBytes), tmp,
|
||||
(const byte*)vects[i].input, (word32)vects[i].inLen, iv), 0);
|
||||
ExpectBufEQ(tmp, vects[i].output, vects[i].outLen);
|
||||
XMEMSET(tmp, 0, sizeof(tmp));
|
||||
ExpectIntEQ(wc_AesCtsDecrypt(keyBytes, sizeof(keyBytes), tmp,
|
||||
(const byte*)vects[i].output, (word32)vects[i].outLen, iv), 0);
|
||||
ExpectBufEQ(tmp, vects[i].input, vects[i].inLen);
|
||||
}
|
||||
/* Execute all branches */
|
||||
{
|
||||
Aes* aes = NULL;
|
||||
int result_code = 0;
|
||||
const byte* in = (const byte*)vects[5].input;
|
||||
byte* out = tmp;
|
||||
word32 outSz = (word32)vects[5].outLen;
|
||||
word32 remSz = (word32)vects[5].outLen;
|
||||
|
||||
XMEMSET(tmp, 0, sizeof(tmp));
|
||||
ExpectNotNull(aes = wc_AesNew(NULL, INVALID_DEVID, &result_code));
|
||||
ExpectIntEQ(wc_AesSetKey(aes, keyBytes, sizeof(keyBytes), iv,
|
||||
AES_ENCRYPTION), 0);
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 1), 0);
|
||||
in += 1; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 31), 0);
|
||||
in += 31; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 32), 0);
|
||||
in += 32; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptFinal(aes, out, &outSz), 0);
|
||||
remSz -= outSz;
|
||||
ExpectIntEQ(remSz, 0);
|
||||
ExpectBufEQ(tmp, vects[5].output, vects[5].outLen);
|
||||
ExpectIntEQ(wc_AesDelete(aes, &aes), 0);
|
||||
}
|
||||
{
|
||||
Aes* aes = NULL;
|
||||
int result_code = 0;
|
||||
const byte* in = (const byte*)vects[5].input;
|
||||
byte* out = tmp;
|
||||
word32 outSz = (word32)vects[5].outLen;
|
||||
word32 remSz = (word32)vects[5].outLen;
|
||||
|
||||
ExpectNotNull(aes = wc_AesNew(NULL, INVALID_DEVID, &result_code));
|
||||
ExpectIntEQ(wc_AesSetKey(aes, keyBytes, sizeof(keyBytes), iv,
|
||||
AES_ENCRYPTION), 0);
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 1), 0);
|
||||
in += 1; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 63), 0);
|
||||
in += 63; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptFinal(aes, out, &outSz), 0);
|
||||
remSz -= outSz;
|
||||
ExpectIntEQ(remSz, 0);
|
||||
ExpectBufEQ(tmp, vects[5].output, vects[5].outLen);
|
||||
ExpectIntEQ(wc_AesDelete(aes, &aes), 0);
|
||||
}
|
||||
{
|
||||
Aes* aes = NULL;
|
||||
int result_code = 0;
|
||||
const byte* in = (const byte*)vects[2].input;
|
||||
byte* out = tmp;
|
||||
word32 outSz = (word32)vects[2].outLen;
|
||||
word32 remSz = (word32)vects[2].outLen;
|
||||
|
||||
ExpectNotNull(aes = wc_AesNew(NULL, INVALID_DEVID, &result_code));
|
||||
ExpectIntEQ(wc_AesSetKey(aes, keyBytes, sizeof(keyBytes), iv,
|
||||
AES_ENCRYPTION), 0);
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 16), 0);
|
||||
in += 16; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptUpdate(aes, out, &outSz, in, 16), 0);
|
||||
in += 16; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsEncryptFinal(aes, out, &outSz), 0);
|
||||
remSz -= outSz;
|
||||
ExpectIntEQ(remSz, 0);
|
||||
ExpectBufEQ(tmp, vects[2].output, vects[2].outLen);
|
||||
ExpectIntEQ(wc_AesDelete(aes, &aes), 0);
|
||||
}
|
||||
{
|
||||
Aes* aes = NULL;
|
||||
int result_code = 0;
|
||||
const byte* in = (const byte*)vects[5].output;
|
||||
byte* out = tmp;
|
||||
word32 outSz = (word32)vects[5].inLen;
|
||||
word32 remSz = (word32)vects[5].inLen;
|
||||
|
||||
XMEMSET(tmp, 0, sizeof(tmp));
|
||||
ExpectNotNull(aes = wc_AesNew(NULL, INVALID_DEVID, &result_code));
|
||||
ExpectIntEQ(wc_AesSetKey(aes, keyBytes, sizeof(keyBytes), iv,
|
||||
AES_DECRYPTION), 0);
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 1), 0);
|
||||
in += 1; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 31), 0);
|
||||
in += 31; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 32), 0);
|
||||
in += 32; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptFinal(aes, out, &outSz), 0);
|
||||
remSz -= outSz;
|
||||
ExpectIntEQ(remSz, 0);
|
||||
ExpectBufEQ(tmp, vects[5].input, vects[5].inLen);
|
||||
ExpectIntEQ(wc_AesDelete(aes, &aes), 0);
|
||||
}
|
||||
{
|
||||
Aes* aes = NULL;
|
||||
int result_code = 0;
|
||||
const byte* in = (const byte*)vects[5].output;
|
||||
byte* out = tmp;
|
||||
word32 outSz = (word32)vects[5].inLen;
|
||||
word32 remSz = (word32)vects[5].inLen;
|
||||
|
||||
ExpectNotNull(aes = wc_AesNew(NULL, INVALID_DEVID, &result_code));
|
||||
ExpectIntEQ(wc_AesSetKey(aes, keyBytes, sizeof(keyBytes), iv,
|
||||
AES_DECRYPTION), 0);
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 1), 0);
|
||||
in += 1; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 63), 0);
|
||||
in += 63; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptFinal(aes, out, &outSz), 0);
|
||||
remSz -= outSz;
|
||||
ExpectIntEQ(remSz, 0);
|
||||
ExpectBufEQ(tmp, vects[5].input, vects[5].inLen);
|
||||
ExpectIntEQ(wc_AesDelete(aes, &aes), 0);
|
||||
}
|
||||
{
|
||||
Aes* aes = NULL;
|
||||
int result_code = 0;
|
||||
const byte* in = (const byte*)vects[2].output;
|
||||
byte* out = tmp;
|
||||
word32 outSz = (word32)vects[2].inLen;
|
||||
word32 remSz = (word32)vects[2].inLen;
|
||||
|
||||
ExpectNotNull(aes = wc_AesNew(NULL, INVALID_DEVID, &result_code));
|
||||
ExpectIntEQ(wc_AesSetKey(aes, keyBytes, sizeof(keyBytes), iv,
|
||||
AES_DECRYPTION), 0);
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 16), 0);
|
||||
in += 16; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptUpdate(aes, out, &outSz, in, 16), 0);
|
||||
in += 16; out += outSz; remSz -= outSz; outSz = remSz;
|
||||
ExpectIntEQ(wc_AesCtsDecryptFinal(aes, out, &outSz), 0);
|
||||
remSz -= outSz;
|
||||
ExpectIntEQ(remSz, 0);
|
||||
ExpectBufEQ(tmp, vects[2].input, vects[2].inLen);
|
||||
ExpectIntEQ(wc_AesDelete(aes, &aes), 0);
|
||||
}
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* AES-CTR
|
||||
******************************************************************************/
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
int test_wc_AesSetKey(void);
|
||||
int test_wc_AesSetIV(void);
|
||||
int test_wc_AesCbcEncryptDecrypt(void);
|
||||
int test_wc_AesCtsEncryptDecrypt(void);
|
||||
int test_wc_AesCtrEncryptDecrypt(void);
|
||||
int test_wc_AesGcmSetKey(void);
|
||||
int test_wc_AesGcmEncryptDecrypt(void);
|
||||
|
@ -48,6 +49,7 @@ int test_wc_GmacUpdate(void);
|
|||
TEST_DECL_GROUP("aes", test_wc_AesSetKey), \
|
||||
TEST_DECL_GROUP("aes", test_wc_AesSetIV), \
|
||||
TEST_DECL_GROUP("aes", test_wc_AesCbcEncryptDecrypt), \
|
||||
TEST_DECL_GROUP("aes", test_wc_AesCtsEncryptDecrypt), \
|
||||
TEST_DECL_GROUP("aes", test_wc_AesCtrEncryptDecrypt), \
|
||||
TEST_DECL_GROUP("aes", test_wc_AesGcmSetKey), \
|
||||
TEST_DECL_GROUP("aes", test_wc_AesGcmEncryptDecrypt), \
|
||||
|
|
|
@ -3759,7 +3759,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
|
|||
ByteReverseWords(rk, rk, keylen);
|
||||
#endif
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
return wc_AesSetIV(aes, iv);
|
||||
|
@ -3840,7 +3841,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
|
|||
XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
|
||||
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
|
||||
|
@ -3871,7 +3873,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
|
|||
XMEMCPY(aes->key, userKey, keylen);
|
||||
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
|
||||
|
@ -3923,7 +3926,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
|
|||
return BAD_FUNC_ARG;
|
||||
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
|
||||
|
@ -4004,7 +4008,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
|
|||
ret = nrf51_aes_set_key(userKey);
|
||||
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
|
||||
|
@ -4061,7 +4066,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(
|
|||
|
||||
XMEMCPY(aes->key, userKey, keylen);
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
return wc_AesSetIV(aes, iv);
|
||||
|
@ -4554,7 +4560,8 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
|
|||
}
|
||||
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
aes->left = 0;
|
||||
#endif
|
||||
|
||||
|
@ -4836,7 +4843,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
|
|||
XMEMSET(aes->reg, 0, WC_AES_BLOCK_SIZE);
|
||||
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
/* Clear any unused bytes from last cipher op. */
|
||||
aes->left = 0;
|
||||
#endif
|
||||
|
@ -10857,7 +10865,7 @@ int wc_GmacVerify(const byte* key, word32 keySz,
|
|||
#endif /* WC_NO_RNG */
|
||||
|
||||
|
||||
WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
|
||||
int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
|
||||
{
|
||||
if (gmac == NULL || key == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
|
@ -10866,7 +10874,7 @@ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
|
|||
}
|
||||
|
||||
|
||||
WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
|
||||
int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
|
||||
const byte* authIn, word32 authInSz,
|
||||
byte* authTag, word32 authTagSz)
|
||||
{
|
||||
|
@ -14906,4 +14914,278 @@ int wc_AesEaxFree(AesEax* eax)
|
|||
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
#ifdef WOLFSSL_AES_CTS
|
||||
|
||||
|
||||
/* One-shot API */
|
||||
int wc_AesCtsEncrypt(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* iv)
|
||||
{
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
Aes *aes = NULL;
|
||||
#else
|
||||
Aes _aes;
|
||||
Aes *aes = &_aes;
|
||||
#endif
|
||||
int ret = 0;
|
||||
word32 outSz = inSz;
|
||||
|
||||
if (key == NULL || out == NULL || in == NULL || iv == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
aes = wc_AesNew(NULL, INVALID_DEVID, &ret);
|
||||
#else
|
||||
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION);
|
||||
if (ret == 0)
|
||||
ret = wc_AesCtsEncryptUpdate(aes, out, &outSz, in, inSz);
|
||||
if (ret == 0) {
|
||||
out += outSz;
|
||||
outSz = inSz - outSz;
|
||||
ret = wc_AesCtsEncryptFinal(aes, out, &outSz);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
wc_AesDelete(aes, NULL);
|
||||
#else
|
||||
wc_AesFree(aes);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_AesCtsDecrypt(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* iv)
|
||||
{
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
Aes *aes = NULL;
|
||||
#else
|
||||
Aes _aes;
|
||||
Aes *aes = &_aes;
|
||||
#endif
|
||||
int ret = 0;
|
||||
word32 outSz = inSz;
|
||||
|
||||
if (key == NULL || out == NULL || in == NULL || iv == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
aes = wc_AesNew(NULL, INVALID_DEVID, &ret);
|
||||
#else
|
||||
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION);
|
||||
if (ret == 0)
|
||||
ret = wc_AesCtsDecryptUpdate(aes, out, &outSz, in, inSz);
|
||||
if (ret == 0) {
|
||||
out += outSz;
|
||||
outSz = inSz - outSz;
|
||||
ret = wc_AesCtsDecryptFinal(aes, out, &outSz);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
wc_AesDelete(aes, NULL);
|
||||
#else
|
||||
wc_AesFree(aes);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int AesCtsUpdate(Aes* aes, byte* out, word32* outSz,
|
||||
const byte* in, word32 inSz, int enc)
|
||||
{
|
||||
word32 blocks = 0;
|
||||
int ret = 0;
|
||||
word32 writtenSz = 0;
|
||||
word32 tmpOutSz;
|
||||
|
||||
if (aes == NULL || out == NULL || in == NULL || outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* Error out early for easy sanity check */
|
||||
if (*outSz < inSz)
|
||||
return BUFFER_E;
|
||||
tmpOutSz = *outSz;
|
||||
|
||||
/* We need to store last two blocks of plaintext */
|
||||
if (aes->left > 0) {
|
||||
word32 copySz = min(inSz, (WC_AES_BLOCK_SIZE * 2) - aes->left);
|
||||
XMEMCPY(aes->ctsBlock + aes->left, in, copySz);
|
||||
aes->left += copySz;
|
||||
in += copySz;
|
||||
inSz -= copySz;
|
||||
|
||||
if (aes->left == WC_AES_BLOCK_SIZE * 2) {
|
||||
if (inSz > WC_AES_BLOCK_SIZE) {
|
||||
if (tmpOutSz < WC_AES_BLOCK_SIZE * 2)
|
||||
return BUFFER_E;
|
||||
if (enc) {
|
||||
ret = wc_AesCbcEncrypt(aes, out, aes->ctsBlock,
|
||||
WC_AES_BLOCK_SIZE * 2);
|
||||
}
|
||||
else {
|
||||
ret = wc_AesCbcDecrypt(aes, out, aes->ctsBlock,
|
||||
WC_AES_BLOCK_SIZE * 2);
|
||||
}
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
out += WC_AES_BLOCK_SIZE * 2;
|
||||
writtenSz += WC_AES_BLOCK_SIZE * 2;
|
||||
tmpOutSz -= WC_AES_BLOCK_SIZE * 2;
|
||||
aes->left = 0;
|
||||
}
|
||||
else if (inSz > 0) {
|
||||
if (tmpOutSz < WC_AES_BLOCK_SIZE)
|
||||
return BUFFER_E;
|
||||
if (enc) {
|
||||
ret = wc_AesCbcEncrypt(aes, out, aes->ctsBlock,
|
||||
WC_AES_BLOCK_SIZE);
|
||||
}
|
||||
else {
|
||||
ret = wc_AesCbcDecrypt(aes, out, aes->ctsBlock,
|
||||
WC_AES_BLOCK_SIZE);
|
||||
}
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
out += WC_AES_BLOCK_SIZE;
|
||||
writtenSz += WC_AES_BLOCK_SIZE;
|
||||
tmpOutSz -= WC_AES_BLOCK_SIZE;
|
||||
/* Move the last block in ctsBlock to the beginning for
|
||||
* next operation */
|
||||
XMEMCPY(aes->ctsBlock, aes->ctsBlock + WC_AES_BLOCK_SIZE,
|
||||
WC_AES_BLOCK_SIZE);
|
||||
XMEMCPY(aes->ctsBlock + WC_AES_BLOCK_SIZE, in, inSz);
|
||||
aes->left = WC_AES_BLOCK_SIZE + inSz;
|
||||
*outSz = writtenSz;
|
||||
return ret; /* Return the result of encryption */
|
||||
}
|
||||
else {
|
||||
/* Can't output data as we need > 1 block for Final call */
|
||||
*outSz = writtenSz;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* All input has been absorbed into aes->ctsBlock */
|
||||
*outSz = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (inSz > WC_AES_BLOCK_SIZE) {
|
||||
/* We need to store the last two full or partial blocks */
|
||||
blocks = (inSz + (WC_AES_BLOCK_SIZE - 1)) / WC_AES_BLOCK_SIZE;
|
||||
blocks -= 2;
|
||||
}
|
||||
if (tmpOutSz < blocks * WC_AES_BLOCK_SIZE)
|
||||
return BUFFER_E;
|
||||
if (enc)
|
||||
ret = wc_AesCbcEncrypt(aes, out, in, blocks * WC_AES_BLOCK_SIZE);
|
||||
else
|
||||
ret = wc_AesCbcDecrypt(aes, out, in, blocks * WC_AES_BLOCK_SIZE);
|
||||
in += blocks * WC_AES_BLOCK_SIZE;
|
||||
inSz -= blocks * WC_AES_BLOCK_SIZE;
|
||||
XMEMCPY(aes->ctsBlock, in, inSz);
|
||||
aes->left = inSz;
|
||||
writtenSz += blocks * WC_AES_BLOCK_SIZE;
|
||||
*outSz = writtenSz;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Incremental API */
|
||||
int wc_AesCtsEncryptUpdate(Aes* aes, byte* out, word32* outSz,
|
||||
const byte* in, word32 inSz)
|
||||
{
|
||||
return AesCtsUpdate(aes, out, outSz, in, inSz, 1);
|
||||
}
|
||||
|
||||
int wc_AesCtsEncryptFinal(Aes* aes, byte* out, word32* outSz)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (aes == NULL || out == NULL || outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (*outSz < aes->left)
|
||||
return BUFFER_E;
|
||||
|
||||
/* Input must be at least two complete or partial blocks */
|
||||
if (aes->left <= WC_AES_BLOCK_SIZE)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* Zero padding */
|
||||
XMEMSET(aes->ctsBlock + aes->left, 0, (WC_AES_BLOCK_SIZE * 2) - aes->left);
|
||||
|
||||
ret = wc_AesCbcEncrypt(aes, aes->ctsBlock, aes->ctsBlock,
|
||||
WC_AES_BLOCK_SIZE * 2);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
XMEMCPY(out, aes->ctsBlock + WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE);
|
||||
XMEMCPY(out + WC_AES_BLOCK_SIZE, aes->ctsBlock,
|
||||
aes->left - WC_AES_BLOCK_SIZE);
|
||||
*outSz = aes->left;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_AesCtsDecryptUpdate(Aes* aes, byte* out, word32* outSz,
|
||||
const byte* in, word32 inSz)
|
||||
{
|
||||
return AesCtsUpdate(aes, out, outSz, in, inSz, 0);
|
||||
}
|
||||
|
||||
int wc_AesCtsDecryptFinal(Aes* aes, byte* out, word32* outSz)
|
||||
{
|
||||
int ret = 0;
|
||||
byte iv[WC_AES_BLOCK_SIZE];
|
||||
byte tmp[WC_AES_BLOCK_SIZE];
|
||||
word32 partialSz;
|
||||
word32 padSz;
|
||||
|
||||
if (aes == NULL || out == NULL || outSz == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (*outSz < aes->left)
|
||||
return BUFFER_E;
|
||||
|
||||
/* Input must be at least two complete or partial blocks */
|
||||
if (aes->left <= WC_AES_BLOCK_SIZE)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
partialSz = aes->left - WC_AES_BLOCK_SIZE;
|
||||
padSz = 2 * WC_AES_BLOCK_SIZE - aes->left;
|
||||
/* Zero pad */
|
||||
XMEMSET(aes->ctsBlock + aes->left, 0, padSz);
|
||||
|
||||
/* Store IV */
|
||||
XMEMCPY(iv, aes->reg, WC_AES_BLOCK_SIZE);
|
||||
/* Load IV */
|
||||
XMEMCPY(aes->reg, aes->ctsBlock + WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE);
|
||||
|
||||
ret = wc_AesCbcDecrypt(aes, tmp, aes->ctsBlock, WC_AES_BLOCK_SIZE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* Write out partial block */
|
||||
XMEMCPY(out + WC_AES_BLOCK_SIZE, tmp, partialSz);
|
||||
/* Retrieve the padding */
|
||||
XMEMCPY(aes->ctsBlock + aes->left, tmp + partialSz, padSz);
|
||||
/* Restore IV */
|
||||
XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE);
|
||||
|
||||
ret = wc_AesCbcDecrypt(aes, out, aes->ctsBlock + WC_AES_BLOCK_SIZE,
|
||||
WC_AES_BLOCK_SIZE);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
*outSz = aes->left;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_AES_CTS */
|
||||
|
||||
|
||||
#endif /* !NO_AES */
|
||||
|
|
|
@ -334,7 +334,8 @@ struct Aes {
|
|||
WC_ASYNC_DEV asyncDev;
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT */
|
||||
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS)
|
||||
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
|
||||
defined(WOLFSSL_AES_CTS)
|
||||
word32 left; /* unused bytes left from last call */
|
||||
#endif
|
||||
#ifdef WOLFSSL_XILINX_CRYPT
|
||||
|
@ -425,6 +426,9 @@ struct Aes {
|
|||
* trackable by sanitizers.
|
||||
*/
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_CTS
|
||||
byte ctsBlock[WC_AES_BLOCK_SIZE * 2];
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef WC_AES_TYPE_DEFINED
|
||||
|
@ -849,6 +853,28 @@ WOLFSSL_API int wc_AesEaxFree(AesEax* eax);
|
|||
|
||||
#endif /* WOLFSSL_AES_EAX */
|
||||
|
||||
#ifdef WOLFSSL_AES_CTS
|
||||
/* Ciphertext stealing encryption compatible with RFC2040 and RFC3962. */
|
||||
|
||||
/* One-shot API */
|
||||
WOLFSSL_API int wc_AesCtsEncrypt(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* iv);
|
||||
WOLFSSL_API int wc_AesCtsDecrypt(const byte* key, word32 keySz, byte* out,
|
||||
const byte* in, word32 inSz,
|
||||
const byte* iv);
|
||||
|
||||
/* Incremental API */
|
||||
WOLFSSL_API int wc_AesCtsEncryptUpdate(Aes* aes, byte* out, word32* outSz,
|
||||
const byte* in, word32 inSz);
|
||||
WOLFSSL_API int wc_AesCtsDecryptUpdate(Aes* aes, byte* out, word32* outSz,
|
||||
const byte* in, word32 inSz);
|
||||
WOLFSSL_API int wc_AesCtsEncryptFinal(Aes* aes, byte* out, word32* outSz);
|
||||
WOLFSSL_API int wc_AesCtsDecryptFinal(Aes* aes, byte* out, word32* outSz);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__) && defined(WOLFSSL_ARMASM) && \
|
||||
!defined(WOLFSSL_ARMASM_NO_HW_CRYPTO)
|
||||
|
||||
|
|
|
@ -3170,6 +3170,11 @@ extern void uITRON4_free(void *p) ;
|
|||
#define WOLFSSL_AES_DIRECT
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_CTS
|
||||
#if defined(NO_AES_CBC) || !defined(HAVE_AES_CBC)
|
||||
#error "AES CTS requires AES CBC"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_TLS12)) || \
|
||||
|
|
Loading…
Reference in New Issue