diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 3eb781f1f..51014cbf7 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -7476,6 +7476,196 @@ int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) return wc_AesFeedbackDecrypt(aes, out, in, sz, AES_CFB_MODE); } #endif /* HAVE_AES_DECRYPT */ + + +/* shift the whole AES_BLOCK_SIZE array left by 8 or 1 bits */ +static void shiftLeftArray(byte* ary, byte shift) +{ + int i; + + if (shift == WOLFSSL_BIT_SIZE) { + /* shifting over by 8 bits */ + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) { + ary[i] = ary[i+1]; + } + ary[i] = 0; + } + else { + byte carry = 0; + + /* shifting over by 7 or less bits */ + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) { + carry = ary[i+1] & (0XFF << (WOLFSSL_BIT_SIZE - shift)); + carry >>= (WOLFSSL_BIT_SIZE - shift); + ary[i] = (ary[i] << shift) + carry; + } + ary[i] = ary[i] << shift; + } +} + + +/* returns 0 on success and negative values on failure */ +static int wc_AesFeedbackCFB8(Aes* aes, byte* out, const byte* in, + word32 sz, byte dir) +{ + byte *pt; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (sz > 0) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + if (dir == AES_DECRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + shiftLeftArray(pt, WOLFSSL_BIT_SIZE); + pt[AES_BLOCK_SIZE - 1] = in[0]; + } + + /* MSB + XOR */ + out[0] = aes->tmp[0] ^ in[0]; + if (dir == AES_ENCRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + shiftLeftArray(pt, WOLFSSL_BIT_SIZE); + pt[AES_BLOCK_SIZE - 1] = out[0]; + } + + out += 1; + in += 1; + sz -= 1; + } + + return 0; +} + + +/* returns 0 on success and negative values on failure */ +static int wc_AesFeedbackCFB1(Aes* aes, byte* out, const byte* in, + word32 sz, byte dir) +{ + byte tmp; + byte* pt; + int bit = 7; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + out[0] = 0; + while (sz > 0) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + if (dir == AES_DECRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + tmp = (0X01 << bit) & in[0]; + tmp = tmp >> bit; + shiftLeftArray((byte*)aes->reg, 1); + pt[AES_BLOCK_SIZE - 1] |= tmp; + } + + /* MSB + XOR */ + tmp = (0X01 << bit) & in[0]; + pt = (byte*)aes->tmp; + tmp = pt[0] ^ (tmp >> bit); + tmp &= 0x01; + out[0] |= (tmp << bit); + + + if (dir == AES_ENCRYPTION) { + pt = (byte*)aes->reg; + + /* LSB + CAT */ + shiftLeftArray((byte*)aes->reg, 1); + pt[AES_BLOCK_SIZE - 1] |= tmp; + } + + bit--; + if (bit < 0) { + out += 1; + in += 1; + sz -= 1; + bit = 7; + if (sz > 0) { + out[0] = 0; + } + } + else { + sz -= 1; + } + } + + return 0; +} + + +/* CFB 1 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb1Encrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB1(aes, out, in, sz, AES_ENCRYPTION); +} + + +/* CFB 8 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb8Encrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB8(aes, out, in, sz, AES_ENCRYPTION); +} +#ifdef HAVE_AES_DECRYPT + +/* CFB 1 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb1Decrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB1(aes, out, in, sz, AES_DECRYPTION); +} + + +/* CFB 8 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative values on failure + */ +int wc_AesCfb8Decrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_AesFeedbackCFB8(aes, out, in, sz, AES_DECRYPTION); +} +#endif /* HAVE_AES_DECRYPT */ #endif /* WOLFSSL_AES_CFB */ #ifdef WOLFSSL_AES_OFB @@ -7513,7 +7703,7 @@ int wc_AesOfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) return wc_AesFeedbackDecrypt(aes, out, in, sz, AES_OFB_MODE); } #endif /* HAVE_AES_DECRYPT */ -#endif /* WOLFSSL_AES_CFB */ +#endif /* WOLFSSL_AES_OFB */ #ifdef HAVE_AES_KEYWRAP diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e0655e27e..31c01283b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5863,8 +5863,156 @@ int des3_test(void) return ret; } + + + static int aescfb1_test(void) + { + Aes enc; + byte cipher[AES_BLOCK_SIZE]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE]; + #endif + int ret = 0; + + const byte iv[] = { + 0x4d,0xbb,0xdc,0xaa,0x59,0xf3,0x63,0xc9, + 0x2a,0x3b,0x98,0x43,0xad,0x20,0xe2,0xb7 + }; + +#ifdef WOLFSSL_AES_128 + const byte key1[] = + { + 0xcd,0xef,0x9d,0x06,0x61,0xba,0xe4,0x73, + 0x8d,0x1a,0x58,0xa2,0xa6,0x22,0x8b,0x66 + }; + + const byte cipher1[] = + { + 0x00 + }; + + const byte msg1[] = + { + 0xC0 + }; +#endif /* WOLFSSL_AES_128 */ + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4739; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4740; +#endif + +#ifdef WOLFSSL_AES_128 + /* 128 key tests */ + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4741; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4742; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(&enc, cipher, msg1, 2); + if (ret != 0) + return -4743; + + if (cipher[0] != cipher1[0]) + return -4744; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfb1Decrypt(&dec, plain, cipher, 2); + if (ret != 0) + return -4745; + + if (plain[0] != msg1[0]) + return -4746; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_128 */ + + return ret; + } + + static int aescfb8_test(void) + { + Aes enc; + byte cipher[AES_BLOCK_SIZE]; + #ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain [AES_BLOCK_SIZE]; + #endif + int ret = 0; + + const byte iv[] = { + 0xf4,0x75,0xc6,0x49,0x91,0xb2,0x0e,0xae, + 0xe1,0x83,0xa2,0x26,0x29,0xe2,0x1e,0x22 + }; + +#ifdef WOLFSSL_AES_128 + const byte key1[] = + { + 0xc8,0xfe,0x9b,0xf7,0x7b,0x93,0x0f,0x46, + 0xd2,0x07,0x8b,0x8c,0x0e,0x65,0x7c,0xd4 + }; + + const byte cipher1[] = + { + 0xd2,0x76,0x91 + }; + + const byte msg1[] = + { + 0xc9,0x06,0x35 + }; +#endif /* WOLFSSL_AES_128 */ + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4739; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4740; +#endif + +#ifdef WOLFSSL_AES_128 + /* 128 key tests */ + ret = wc_AesSetKey(&enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4741; + #ifdef HAVE_AES_DECRYPT + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(&dec, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); + if (ret != 0) + return -4742; + #endif + + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb8Encrypt(&enc, cipher, msg1, sizeof(msg1)); + if (ret != 0) + return -4743; + + if (XMEMCMP(cipher, cipher1, sizeof(cipher1)) != 0) + return -4744; + + #ifdef HAVE_AES_DECRYPT + ret = wc_AesCfb8Decrypt(&dec, plain, cipher, sizeof(msg1)); + if (ret != 0) + return -4745; + + if (XMEMCMP(plain, msg1, sizeof(msg1)) != 0) + return -4746; + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_128 */ + + return ret; + } #endif /* WOLFSSL_AES_CFB */ + #ifdef WOLFSSL_AES_OFB #ifdef OPENSSL_EXTRA /* pass in the function, key, iv, plain text and expected and this function @@ -7476,6 +7624,14 @@ int aes_test(void) ret = aescfb_test(); if (ret != 0) return ret; + + ret = aescfb1_test(); + if (ret != 0) + return ret; + + ret = aescfb8_test(); + if (ret != 0) + return ret; #endif diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 91aae2c09..858291849 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -277,9 +277,17 @@ WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, #ifdef WOLFSSL_AES_CFB WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb1Encrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb8Encrypt(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); +WOLFSSL_API int wc_AesCfb1Decrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCfb8Decrypt(Aes* aes, byte* out, + const byte* in, word32 sz); #endif /* HAVE_AES_DECRYPT */ #endif /* WOLFSSL_AES_CFB */