From 2eb253330fd88b9be9176c536f1733380c558036 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 25 Feb 2021 20:01:51 +0100 Subject: [PATCH 1/2] 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 --- src/ssl.c | 44 ++++++++++ tests/api.c | 28 +++++++ wolfcrypt/src/aes.c | 176 +++++++++++++++++++++------------------- wolfssl/openssl/aes.h | 8 ++ wolfssl/wolfcrypt/aes.h | 8 ++ 5 files changed, 182 insertions(+), 82 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 5ef8c4f21..1d31312da 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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 diff --git a/tests/api.c b/tests/api.c index 85436a5ff..e77cb055e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -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 } diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index b08a5c69f..cd1e4deff 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -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,35 +8949,59 @@ 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; + 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) +/* 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 Aes *aes = NULL; #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); + 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; + return ret; } #endif /* HAVE_AES_KEYWRAP */ diff --git a/wolfssl/openssl/aes.h b/wolfssl/openssl/aes.h index f66b57411..da4baa7c6 100644 --- a/wolfssl/openssl/aes.h +++ b/wolfssl/openssl/aes.h @@ -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 diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 1141b0c71..707e19f06 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -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 From 39a28eeec254c05cb9d4c9ccfa8a2fad4612fd24 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 26 Feb 2021 18:07:34 +0100 Subject: [PATCH 2/2] Add RSA_NO_PADDING to wolfSSL_RSA_private_encrypt --- src/ssl.c | 52 ++++++++++++++++++++++++++++++++++----------- tests/api.c | 4 +++- wolfcrypt/src/aes.c | 2 +- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 1d31312da..ebfe969fd 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -29466,12 +29466,12 @@ void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out, #endif /* WOLFSSL_AES_CFB */ } -#ifdef HAVE_AES_KEYWRAP +/* wc_AesKey*Wrap_ex API not available in FIPS and SELFTEST */ +#if defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) 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"); @@ -29481,9 +29481,7 @@ int wolfSSL_AES_wrap_key(AES_KEY *key, const unsigned char *iv, return WOLFSSL_FAILURE; } - aes = (Aes*)key; - - ret = wc_AesKeyWrap_ex(aes, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv); + ret = wc_AesKeyWrap_ex((Aes*)key, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv); return ret < 0 ? WOLFSSL_FAILURE : ret; } @@ -29492,7 +29490,6 @@ 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"); @@ -29502,13 +29499,11 @@ int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv, return WOLFSSL_FAILURE; } - aes = (Aes*)key; - - ret = wc_AesKeyUnWrap_ex(aes, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv); + ret = wc_AesKeyUnWrap_ex((Aes*)key, in, inlen, out, inlen + KEYWRAP_BLOCK_SIZE, iv); return ret < 0 ? WOLFSSL_FAILURE : ret; } -#endif /* HAVE_AES_KEYWRAP */ +#endif /* HAVE_AES_KEYWRAP && !HAVE_FIPS && !HAVE_SELFTEST */ #endif /* NO_AES */ #ifndef NO_FILESYSTEM @@ -49765,7 +49760,14 @@ int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, return 0; } - if (padding != RSA_PKCS1_PADDING && padding != RSA_PKCS1_PSS_PADDING) { + if ( + #ifdef WC_RSA_PSS + padding != RSA_PKCS1_PSS_PADDING && + #endif + #ifdef WC_RSA_NO_PADDING + padding != RSA_NO_PADDING && + #endif + padding != RSA_PKCS1_PADDING) { WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding"); return 0; } @@ -49797,7 +49799,33 @@ int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, #endif /* size of output buffer must be size of RSA key */ - sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng); + switch (padding) { + case RSA_PKCS1_PADDING: + sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), + key, rng); + break; + #ifdef WC_RSA_PSS + case RSA_PKCS1_PSS_PADDING: + sz = wc_RsaPSS_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), + WC_HASH_TYPE_NONE, WC_MGF1NONE, key, rng); + break; + #endif + #ifdef WC_RSA_NO_PADDING + case RSA_NO_PADDING: + { + word32 outLen = (word32)len; + sz = wc_RsaFunction(in, (word32)len, out, &outLen, + RSA_PRIVATE_ENCRYPT, key, rng); + if (sz == 0) + sz = (int)outLen; + break; + } + #endif + default: + sz = BAD_FUNC_ARG; + break; + } + #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA) if (wc_FreeRng(rng) != 0) { WOLFSSL_MSG("Error freeing random number generator"); diff --git a/tests/api.c b/tests/api.c index e77cb055e..1b884c351 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33608,7 +33608,7 @@ static void test_wolfSSL_AES_cbc_encrypt() #endif - #ifdef HAVE_AES_KEYWRAP + #if defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) byte wrapCipher[sizeof(key256) + KEYWRAP_BLOCK_SIZE] = { 0 }; byte wrapPlain[sizeof(key256)] = { 0 }; byte wrapIV[KEYWRAP_BLOCK_SIZE] = { 0 }; @@ -33621,6 +33621,7 @@ static void test_wolfSSL_AES_cbc_encrypt() 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)); + AssertIntEQ(XMEMCMP(wrapPlain, key256, sizeof(key256)), 0); printf(resultFmt, "passed"); XMEMSET(wrapCipher, 0, sizeof(wrapCipher)); XMEMSET(wrapPlain, 0, sizeof(wrapPlain)); @@ -33633,6 +33634,7 @@ static void test_wolfSSL_AES_cbc_encrypt() 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)); + AssertIntEQ(XMEMCMP(wrapPlain, key256, sizeof(key256)), 0); printf(resultFmt, "passed"); #endif /* HAVE_AES_KEYWRAP */ #endif /* WOLFSSL_AES_256 */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index cd1e4deff..2d67233cd 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -9011,7 +9011,7 @@ int wc_AesKeyUnWrap_ex(Aes *aes, const byte* in, word32 inSz, byte* out, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; - if (in == NULL || inSz < 3 || + if (aes == NULL || in == NULL || inSz < 3 || out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE)) return BAD_FUNC_ARG;