diff --git a/aes.c b/aes.c index eaf2b69..dd77999 100644 --- a/aes.c +++ b/aes.c @@ -480,20 +480,18 @@ void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) #endif // #if defined(ECB) && (ECB == 1) - - - -#if defined(CBC) && (CBC == 1) - - +#if (defined(CBC) && (CBC == 1)) || (defined(CFB) && (CFB == 1)) static void XorWithIv(uint8_t* buf, const uint8_t* Iv) { - uint8_t i; - for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size - { - buf[i] ^= Iv[i]; - } + uint8_t i; + for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size + { + buf[i] ^= Iv[i]; + } } +#endif + +#if defined(CBC) && (CBC == 1) void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) { @@ -551,7 +549,7 @@ void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) { /* inc will overflow */ if (ctx->Iv[bi] == 255) - { + { ctx->Iv[bi] = 0; continue; } @@ -567,3 +565,34 @@ void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) #endif // #if defined(CTR) && (CTR == 1) +#if defined(CFB) && (CFB == 1) + + +void AES_CFB_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) +{ + uintptr_t i; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + Cipher((state_t*)ctx->Iv, ctx->RoundKey); + XorWithIv(buf, ctx->Iv); + memcpy(ctx->Iv, buf, AES_BLOCKLEN); + buf += AES_BLOCKLEN; + } +} + +void AES_CFB_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) +{ + uintptr_t i; + uint8_t storeNextIv[AES_BLOCKLEN]; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + memcpy(storeNextIv, buf, AES_BLOCKLEN); + Cipher((state_t*)ctx->Iv, ctx->RoundKey); + XorWithIv(buf, ctx->Iv); + memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); + buf += AES_BLOCKLEN; + } + +} + +#endif // #if defined(CFB) && (CFB == 1) \ No newline at end of file diff --git a/aes.h b/aes.h index 0d3b2e0..0b9c146 100644 --- a/aes.h +++ b/aes.h @@ -22,6 +22,10 @@ #define CTR 1 #endif +#ifndef CFB + #define CFB 1 +#endif + #define AES128 1 //#define AES192 1 @@ -43,13 +47,13 @@ struct AES_ctx { uint8_t RoundKey[AES_keyExpSize]; -#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) || (defined(CFB) && (CFB == 1)) uint8_t Iv[AES_BLOCKLEN]; #endif }; void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); -#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) || (defined(CFB) && (CFB == 1)) void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); #endif @@ -87,4 +91,15 @@ void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); #endif // #if defined(CTR) && (CTR == 1) +#if defined(CFB) && (CFB == 1) +// buffer size MUST be mutile of AES_BLOCKLEN; +// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme +// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() +// no IV should ever be reused with the same key +void AES_CFB_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); +void AES_CFB_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); + +#endif // #if defined(CFB) && (CFB == 1) + + #endif // _AES_H_ diff --git a/test.c b/test.c index 6796283..262194f 100644 --- a/test.c +++ b/test.c @@ -18,6 +18,8 @@ static int test_encrypt_ctr(void); static int test_decrypt_ctr(void); static int test_encrypt_ecb(void); static int test_decrypt_ecb(void); +static int test_encrypt_cfb(void); +static int test_decrypt_cfb(void); static void test_encrypt_ecb_verbose(void); @@ -38,7 +40,8 @@ int main(void) exit = test_encrypt_cbc() + test_decrypt_cbc() + test_encrypt_ctr() + test_decrypt_ctr() + - test_decrypt_ecb() + test_encrypt_ecb(); + test_decrypt_ecb() + test_encrypt_ecb() + + test_encrypt_cfb() + test_decrypt_cfb(); test_encrypt_ecb_verbose(); return exit; @@ -314,3 +317,64 @@ static int test_decrypt_ecb(void) } +static int test_decrypt_cfb(void) +{ + +#if defined(AES128) + uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + uint8_t out[] = { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 }; + uint8_t iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + uint8_t in[] = { 0x26, 0xb7, 0xcc, 0x60, 0x18, 0x74, 0x80, 0xf0, 0x14, 0xe0, 0xb9, 0x72, 0x89, 0x46, 0xf5, 0x1d, + 0x48, 0xed, 0x40, 0x27, 0x59, 0x03, 0xbc, 0x8b, 0x9f, 0xf2, 0x7d, 0x3b, 0x1b, 0x20, 0x23, 0x45, + 0xeb, 0x0b, 0xa3, 0xbf, 0x0f, 0xf3, 0x63, 0xea, 0x23, 0xff, 0xc0, 0xf9, 0xc4, 0x2b, 0x6c, 0x87, + 0x0b, 0xaa, 0x99, 0xce, 0x5f, 0x13, 0xe6, 0x7d, 0x4e, 0xea, 0xe6, 0x8b, 0x3f, 0x00, 0x8c, 0x71 }; +#endif +// uint8_t buffer[64]; + struct AES_ctx ctx; + + AES_init_ctx_iv(&ctx, key, iv); + AES_CFB_decrypt_buffer(&ctx, in, 64); + + printf("CFB decrypt: "); + + if (0 == memcmp((char*) out, (char*) in, 64)) { + printf("SUCCESS!\n"); + return(0); + } else { + printf("FAILURE!\n"); + return(1); + } +} + +static int test_encrypt_cfb(void) +{ +#if defined(AES128) + uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + uint8_t in[] = { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 }; + uint8_t iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + uint8_t out[] = { 0x26, 0xb7, 0xcc, 0x60, 0x18, 0x74, 0x80, 0xf0, 0x14, 0xe0, 0xb9, 0x72, 0x89, 0x46, 0xf5, 0x1d, + 0x48, 0xed, 0x40, 0x27, 0x59, 0x03, 0xbc, 0x8b, 0x9f, 0xf2, 0x7d, 0x3b, 0x1b, 0x20, 0x23, 0x45, + 0xeb, 0x0b, 0xa3, 0xbf, 0x0f, 0xf3, 0x63, 0xea, 0x23, 0xff, 0xc0, 0xf9, 0xc4, 0x2b, 0x6c, 0x87, + 0x0b, 0xaa, 0x99, 0xce, 0x5f, 0x13, 0xe6, 0x7d, 0x4e, 0xea, 0xe6, 0x8b, 0x3f, 0x00, 0x8c, 0x71 }; +#endif + struct AES_ctx ctx; + + AES_init_ctx_iv(&ctx, key, iv); + AES_CFB_encrypt_buffer(&ctx, in, 64); + + printf("CFB encrypt: "); + + if (0 == memcmp((char*) out, (char*) in, 64)) { + printf("SUCCESS!\n"); + return(0); + } else { + printf("FAILURE!\n"); + return(1); + } +} \ No newline at end of file