Implement AES_wrap_key and AES_unwrap_key

Add `wc_AesKeyWrap_ex` and `wc_AesKeyUnWrap_ex` API to accept an `Aes` object to use for the AES operations
This commit is contained in:
Juliusz Sosinowicz
2021-02-25 20:01:51 +01:00
parent c201b6801c
commit 2eb253330f
5 changed files with 182 additions and 82 deletions

View File

@ -29465,6 +29465,50 @@ void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out,
*num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0;
#endif /* WOLFSSL_AES_CFB */
}
#ifdef HAVE_AES_KEYWRAP
int wolfSSL_AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen)
{
Aes* aes;
int ret;
WOLFSSL_ENTER("wolfSSL_AES_wrap_key");
if (out == NULL || in == NULL) {
WOLFSSL_MSG("Error, Null argument passed in");
return WOLFSSL_FAILURE;
}
aes = (Aes*)key;
ret = wc_AesKeyWrap_ex(aes, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv);
return ret < 0 ? WOLFSSL_FAILURE : ret;
}
int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen)
{
Aes* aes;
int ret;
WOLFSSL_ENTER("wolfSSL_AES_wrap_key");
if (out == NULL || in == NULL) {
WOLFSSL_MSG("Error, Null argument passed in");
return WOLFSSL_FAILURE;
}
aes = (Aes*)key;
ret = wc_AesKeyUnWrap_ex(aes, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv);
return ret < 0 ? WOLFSSL_FAILURE : ret;
}
#endif /* HAVE_AES_KEYWRAP */
#endif /* NO_AES */
#ifndef NO_FILESYSTEM

View File

@ -33607,6 +33607,34 @@ static void test_wolfSSL_AES_cbc_encrypt()
printf(resultFmt, "passed");
#endif
#ifdef HAVE_AES_KEYWRAP
byte wrapCipher[sizeof(key256) + KEYWRAP_BLOCK_SIZE] = { 0 };
byte wrapPlain[sizeof(key256)] = { 0 };
byte wrapIV[KEYWRAP_BLOCK_SIZE] = { 0 };
printf(testingFmt, "wolfSSL_AES_wrap_key() 256-bit NULL iv");
AssertIntEQ(wolfSSL_AES_set_encrypt_key(key256, sizeof(key256)*8, &aes), 0);
AssertIntEQ(wolfSSL_AES_wrap_key(&aes, NULL, wrapCipher, key256,
sizeof(key256)), sizeof(wrapCipher));
printf(resultFmt, "passed");
printf(testingFmt, "wolfSSL_AES_unwrap_key() 256-bit NULL iv");
AssertIntEQ(wolfSSL_AES_set_decrypt_key(key256, sizeof(key256)*8, &aes), 0);
AssertIntEQ(wolfSSL_AES_unwrap_key(&aes, NULL, wrapPlain, wrapCipher,
sizeof(wrapCipher)), sizeof(wrapPlain));
printf(resultFmt, "passed");
XMEMSET(wrapCipher, 0, sizeof(wrapCipher));
XMEMSET(wrapPlain, 0, sizeof(wrapPlain));
printf(testingFmt, "wolfSSL_AES_wrap_key() 256-bit custom iv");
AssertIntEQ(wolfSSL_AES_set_encrypt_key(key256, sizeof(key256)*8, &aes), 0);
AssertIntEQ(wolfSSL_AES_wrap_key(&aes, wrapIV, wrapCipher, key256,
sizeof(key256)), sizeof(wrapCipher));
printf(resultFmt, "passed");
printf(testingFmt, "wolfSSL_AES_unwrap_key() 256-bit custom iv");
AssertIntEQ(wolfSSL_AES_set_decrypt_key(key256, sizeof(key256)*8, &aes), 0);
AssertIntEQ(wolfSSL_AES_unwrap_key(&aes, wrapIV, wrapPlain, wrapCipher,
sizeof(wrapCipher)), sizeof(wrapPlain));
printf(resultFmt, "passed");
#endif /* HAVE_AES_KEYWRAP */
#endif /* WOLFSSL_AES_256 */
#endif
}

View File

@ -8898,25 +8898,18 @@ static WC_INLINE void DecrementKeyWrapCounter(byte* inOutCtr)
}
}
/* perform AES key wrap (RFC3394), return out sz on success, negative on err */
int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
byte* out, word32 outSz, const byte* iv)
int wc_AesKeyWrap_ex(Aes *aes, const byte* in, word32 inSz, byte* out,
word32 outSz, const byte* iv)
{
#ifdef WOLFSSL_SMALL_STACK
Aes *aes = NULL;
#else
Aes aes[1];
#endif
int aes_inited = 0;
byte* r;
word32 i;
int ret, j;
byte* r;
int j;
byte t[KEYWRAP_BLOCK_SIZE];
byte tmp[AES_BLOCK_SIZE];
/* n must be at least 2, output size is n + 8 bytes */
if (key == NULL || in == NULL || inSz < 2 ||
if (aes == NULL || in == NULL || inSz < 2 ||
out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE))
return BAD_FUNC_ARG;
@ -8924,11 +8917,9 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
if (inSz % KEYWRAP_BLOCK_SIZE != 0)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
DYNAMIC_TYPE_AES)) == NULL)
return MEMORY_E;
#endif
r = out + 8;
XMEMCPY(r, in, inSz);
XMEMSET(t, 0, sizeof(t));
/* user IV is optional */
if (iv == NULL) {
@ -8937,23 +8928,8 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE);
}
r = out + 8;
XMEMCPY(r, in, inSz);
XMEMSET(t, 0, sizeof(t));
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0)
goto out;
else
aes_inited = 1;
ret = wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION);
if (ret != 0)
goto out;
for (j = 0; j <= 5; j++) {
for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) {
/* load R[i] */
XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE);
@ -8973,24 +8949,11 @@ int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
/* C[0] = A */
XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE);
ret = 0;
out:
if (aes_inited)
wc_AesFree(aes);
#ifdef WOLFSSL_SMALL_STACK
if (aes)
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
#endif
if (ret != 0)
return ret;
else
return inSz + KEYWRAP_BLOCK_SIZE;
}
int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
/* perform AES key wrap (RFC3394), return out sz on success, negative on err */
int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
byte* out, word32 outSz, const byte* iv)
{
#ifdef WOLFSSL_SMALL_STACK
@ -8998,10 +8961,47 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
#else
Aes aes[1];
#endif
int aes_inited = 0;
int ret;
/* n must be at least 2, output size is n + 8 bytes */
if (key == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
DYNAMIC_TYPE_AES)) == NULL)
return MEMORY_E;
#endif
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0)
goto out;
ret = wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION);
if (ret != 0) {
wc_AesFree(aes);
goto out;
}
ret = wc_AesKeyWrap_ex(aes, in, inSz, out, outSz, iv);
wc_AesFree(aes);
out:
#ifdef WOLFSSL_SMALL_STACK
if (aes != NULL)
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
#endif
return ret;
}
int wc_AesKeyUnWrap_ex(Aes *aes, const byte* in, word32 inSz, byte* out,
word32 outSz, const byte* iv)
{
byte* r;
word32 i, n;
int ret, j;
int j;
byte t[KEYWRAP_BLOCK_SIZE];
byte tmp[AES_BLOCK_SIZE];
@ -9011,9 +9011,7 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
};
(void)iv;
if (key == NULL || in == NULL || inSz < 3 ||
if (in == NULL || inSz < 3 ||
out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE))
return BAD_FUNC_ARG;
@ -9021,34 +9019,17 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
if (inSz % KEYWRAP_BLOCK_SIZE != 0)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
DYNAMIC_TYPE_AES)) == NULL)
return MEMORY_E;
#endif
/* user IV optional */
if (iv != NULL) {
if (iv != NULL)
expIv = iv;
} else {
else
expIv = defaultIV;
}
/* A = C[0], R[i] = C[i] */
XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE);
XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE);
XMEMSET(t, 0, sizeof(t));
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0)
goto out;
else
aes_inited = 1;
ret = wc_AesSetKey(aes, key, keySz, NULL, AES_DECRYPTION);
if (ret != 0)
goto out;
/* initialize counter to 6n */
n = (inSz - 1) / KEYWRAP_BLOCK_SIZE;
InitKeyWrapCounter(t, 6 * n);
@ -9071,24 +9052,55 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
}
/* verify IV */
if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0) {
ret = BAD_KEYWRAP_IV_E;
if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0)
return BAD_KEYWRAP_IV_E;
return inSz - KEYWRAP_BLOCK_SIZE;
}
int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz,
byte* out, word32 outSz, const byte* iv)
{
#ifdef WOLFSSL_SMALL_STACK
Aes *aes = NULL;
#else
Aes aes[1];
#endif
int ret;
(void)iv;
if (key == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
DYNAMIC_TYPE_AES)) == NULL)
return MEMORY_E;
#endif
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0)
goto out;
ret = wc_AesSetKey(aes, key, keySz, NULL, AES_DECRYPTION);
if (ret != 0) {
wc_AesFree(aes);
goto out;
}
out:
ret = wc_AesKeyUnWrap_ex(aes, in, inSz, out, outSz, iv);
if (aes_inited)
wc_AesFree(aes);
out:
#ifdef WOLFSSL_SMALL_STACK
if (aes)
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
#endif
if (ret != 0)
return ret;
else
return inSz - KEYWRAP_BLOCK_SIZE;
}
#endif /* HAVE_AES_KEYWRAP */

View File

@ -59,12 +59,20 @@ WOLFSSL_API void wolfSSL_AES_ecb_encrypt
WOLFSSL_API void wolfSSL_AES_cfb128_encrypt
(const unsigned char *in, unsigned char* out, size_t len,
AES_KEY *key, unsigned char* iv, int* num, const int enc);
WOLFSSL_API int wolfSSL_AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
WOLFSSL_API int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
#define AES_cbc_encrypt wolfSSL_AES_cbc_encrypt
#define AES_ecb_encrypt wolfSSL_AES_ecb_encrypt
#define AES_cfb128_encrypt wolfSSL_AES_cfb128_encrypt
#define AES_set_encrypt_key wolfSSL_AES_set_encrypt_key
#define AES_set_decrypt_key wolfSSL_AES_set_decrypt_key
#define AES_wrap_key wolfSSL_AES_wrap_key
#define AES_unwrap_key wolfSSL_AES_unwrap_key
#ifdef WOLFSSL_AES_DIRECT
WOLFSSL_API void wolfSSL_AES_encrypt

View File

@ -416,10 +416,18 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out,
const byte* in, word32 inSz,
byte* out, word32 outSz,
const byte* iv);
WOLFSSL_API int wc_AesKeyWrap_ex(Aes *aes,
const byte* in, word32 inSz,
byte* out, word32 outSz,
const byte* iv);
WOLFSSL_API int wc_AesKeyUnWrap(const byte* key, word32 keySz,
const byte* in, word32 inSz,
byte* out, word32 outSz,
const byte* iv);
WOLFSSL_API int wc_AesKeyUnWrap_ex(Aes *aes,
const byte* in, word32 inSz,
byte* out, word32 outSz,
const byte* iv);
#endif /* HAVE_AES_KEYWRAP */
#ifdef WOLFSSL_AES_XTS