diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 10971ef55..c7fcd8c63 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -143,6 +143,7 @@ #define BENCH_CHACHA20_POLY1305 0x00002000 #define BENCH_DES 0x00004000 #define BENCH_IDEA 0x00008000 +#define BENCH_AES_CFB 0x00010000 /* Digest algorithms. */ #define BENCH_MD5 0x00000001 #define BENCH_POLY1305 0x00000002 @@ -231,6 +232,9 @@ static const bench_alg bench_cipher_opt[] = { #ifdef WOLFSSL_AES_XTS { "-aes-xts", BENCH_AES_XTS }, #endif +#ifdef HAVE_AES_CFB + { "-aes-cfb", BENCH_AES_CFB }, +#endif #ifdef WOLFSSL_AES_COUNTER { "-aes-ctr", BENCH_AES_CTR }, #endif @@ -1077,6 +1081,10 @@ static void* benchmarks_do(void* args) if (bench_all || (bench_cipher_algs & BENCH_AES_XTS)) bench_aesxts(); #endif +#ifdef HAVE_AES_CFB + if (bench_all || (bench_cipher_algs & BENCH_AES_CFB)) + bench_aescfb(); +#endif #ifdef WOLFSSL_AES_COUNTER if (bench_all || (bench_cipher_algs & BENCH_AES_CTR)) bench_aesctr(); @@ -1904,9 +1912,44 @@ void bench_aesecb(int doAsync) bench_aesecb_internal(doAsync, bench_key, 32, "AES-256-ECB-enc", "AES-256-ECB-dec"); } - #endif /* WOLFSSL_AES_DIRECT */ +#ifdef HAVE_AES_CFB +static void bench_aescfb_internal(const byte* key, word32 keySz, const byte* iv, + const char* label) +{ + Aes enc; + double start; + int i, ret, count; + + ret = wc_AesSetKey(&enc, key, keySz, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + return; + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + if((ret = wc_AesCfbEncrypt(&enc, bench_plain, bench_cipher, + BENCH_SIZE)) != 0) { + printf("wc_AesCfbEncrypt failed, ret = %d\n", ret); + return; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish(label, 0, count, bench_size, start, ret); +} + +void bench_aescfb(void) +{ + bench_aescfb_internal(bench_key, 16, bench_iv, "AES-128-CFB"); + bench_aescfb_internal(bench_key, 24, bench_iv, "AES-192-CFB"); + bench_aescfb_internal(bench_key, 32, bench_iv, "AES-256-CFB"); +} +#endif /* HAVE_AES_CFB */ + #ifdef WOLFSSL_AES_XTS void bench_aesxts(void) diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 2fc43eec8..30d733996 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -53,6 +53,7 @@ void bench_aesccm(void); void bench_aesecb(int); void bench_aesxts(void); void bench_aesctr(void); +void bench_aescfb(void); void bench_poly1305(void); void bench_camellia(void); void bench_md5(int); diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index e8ee908aa..f831f2de4 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -3049,6 +3049,54 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #endif /* AES-CBC block */ #endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_CFB +/* CFB 128 */ +int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / AES_BLOCK_SIZE; + + WOLFSSL_ENTER("wc_AesCfbEncrypt"); + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + wc_AesEncrypt(aes, (byte*)aes->reg, out); + xorbuf(out, in, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, out, AES_BLOCK_SIZE); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + + return 0; +} + + +#ifdef HAVE_AES_DECRYPT +int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / AES_BLOCK_SIZE; + + WOLFSSL_ENTER("wc_AesCfbDecrypt"); + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + wc_AesEncrypt(aes, (byte*)aes->reg, out); + xorbuf(out, in, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, in, AES_BLOCK_SIZE); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CFB */ + #ifdef HAVE_AES_ECB #if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index edfceee74..b03466d88 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -4267,6 +4267,214 @@ int des3_test(void) #ifndef NO_AES +#ifdef HAVE_AES_CFB + /* Test cases from NIST SP 800-38A, Recommendation for Block Cipher Modes of Operation Methods an*/ + static int aescfb_test(void) + { + Aes enc; + byte cipher[AES_BLOCK_SIZE * 4]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE * 4]; + #endif + int ret = 0; + + const byte iv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + }; + + const byte key1[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte cipher1[] = + { + 0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20, + 0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a, + 0xc8,0xa6,0x45,0x37,0xa0,0xb3,0xa9,0x3f, + 0xcd,0xe3,0xcd,0xad,0x9f,0x1c,0xe5,0x8b, + 0x26,0x75,0x1f,0x67,0xa3,0xcb,0xb1,0x40, + 0xb1,0x80,0x8c,0xf1,0x87,0xa4,0xf4,0xdf + }; + + const byte msg1[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef + }; + + /* 192 size key test */ + const byte key2[] = + { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + + const byte cipher2[] = + { + 0xcd,0xc8,0x0d,0x6f,0xdd,0xf1,0x8c,0xab, + 0x34,0xc2,0x59,0x09,0xc9,0x9a,0x41,0x74, + 0x67,0xce,0x7f,0x7f,0x81,0x17,0x36,0x21, + 0x96,0x1a,0x2b,0x70,0x17,0x1d,0x3d,0x7a, + 0x2e,0x1e,0x8a,0x1d,0xd5,0x9b,0x88,0xb1, + 0xc8,0xe6,0x0f,0xed,0x1e,0xfa,0xc4,0xc9, + 0xc0,0x5f,0x9f,0x9c,0xa9,0x83,0x4f,0xa0, + 0x42,0xae,0x8f,0xba,0x58,0x4b,0x09,0xff + }; + + const byte msg2[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + /* 256 size key simple test */ + const byte key3[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + const byte cipher3[] = + { + 0xdc,0x7e,0x84,0xbf,0xda,0x79,0x16,0x4b, + 0x7e,0xcd,0x84,0x86,0x98,0x5d,0x38,0x60, + 0x39,0xff,0xed,0x14,0x3b,0x28,0xb1,0xc8, + 0x32,0x11,0x3c,0x63,0x31,0xe5,0x40,0x7b, + 0xdf,0x10,0x13,0x24,0x15,0xe5,0x4b,0x92, + 0xa1,0x3e,0xd0,0xa8,0x26,0x7a,0xe2,0xf9, + 0x75,0xa3,0x85,0x74,0x1a,0xb9,0xce,0xf8, + 0x20,0x31,0x62,0x3d,0x55,0xb1,0xe4,0x71 + }; + + const byte msg3[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + + /* 128 key tests */ + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -1101; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -1102; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfbEncrypt(&enc, cipher, msg1, AES_BLOCK_SIZE * 2); + if (ret != 0) + return -1105; + + if (XMEMCMP(cipher, cipher1, AES_BLOCK_SIZE * 2)) + return -1106; + + /* test restarting encryption process */ + ret = wc_AesCfbEncrypt(&enc, cipher + (AES_BLOCK_SIZE * 2), + msg1 + (AES_BLOCK_SIZE * 2), AES_BLOCK_SIZE); + if (ret != 0) + return -1107; + + if (XMEMCMP(cipher + (AES_BLOCK_SIZE * 2), + cipher1 + (AES_BLOCK_SIZE * 2), AES_BLOCK_SIZE)) + return -1108; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfbDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE * 3); + if (ret != 0) + return -1109; + + if (XMEMCMP(plain, msg1, AES_BLOCK_SIZE * 3)) + return -1110; + #endif /* HAVE_AES_DECRYPT */ + + /* 192 key size test */ + ret = wc_AesSetKey(&enc, key2, sizeof(key2), iv, AES_ENCRYPTION); + if (ret != 0) + return -1111; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key2, sizeof(key2), iv, AES_ENCRYPTION); + if (ret != 0) + return -1112; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfbEncrypt(&enc, cipher, msg2, AES_BLOCK_SIZE * 4); + if (ret != 0) + return -1113; + + if (XMEMCMP(cipher, cipher2, AES_BLOCK_SIZE * 4)) + return -1114; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfbDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE * 4); + if (ret != 0) + return -1115; + + if (XMEMCMP(plain, msg2, AES_BLOCK_SIZE * 4)) + return -1116; + #endif /* HAVE_AES_DECRYPT */ + + + /* 256 key size test */ + ret = wc_AesSetKey(&enc, key3, sizeof(key3), iv, AES_ENCRYPTION); + if (ret != 0) + return -1117; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key3, sizeof(key3), iv, AES_ENCRYPTION); + if (ret != 0) + return -1118; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfbEncrypt(&enc, cipher, msg3, AES_BLOCK_SIZE * 4); + if (ret != 0) + return -1119; + + if (XMEMCMP(cipher, cipher3, AES_BLOCK_SIZE * 4)) + return -1120; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfbDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE * 4); + if (ret != 0) + return -1121; + + if (XMEMCMP(plain, msg3, AES_BLOCK_SIZE * 4)) + return -1122; + #endif /* HAVE_AES_DECRYPT */ + + return ret; + } +#endif /* HAVE_AES_CFB */ + static int aes_key_size_test(void) { int ret; @@ -5404,6 +5612,12 @@ int aes192_test(void) #endif /* HAVE_AES_CBC */ +#if defined(HAVE_AES_CFB) + ret = aescfb_test(); + if (ret != 0) + return ret; +#endif + return ret; } diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 5ea101c83..aaafc9c5a 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -145,6 +145,15 @@ WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); +#ifdef HAVE_AES_CFB +WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#ifdef HAVE_AES_DECRYPT +WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CFB */ + #ifdef HAVE_AES_ECB WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz);