jump to navigation

Utilizing rijndael source code (bug fix) March 6, 2007

Posted by TSAI HONG-BIN in Programming.
trackback

I downloaded the source code of Rijndael algorithm from the following link.
http://www.cis.syr.edu/~wedu/minix/code.html
It should be an optimized version of Rijndael implementation, especially it is employed and integrated into OpenSSL (aes_core.c).

My purpose is to write a small file encryption tool, using Rijndael obviously, and only Rijndael, in C. Finally I made it, so it’s about time to share my experience here. Somehow I find a problem in this version of Rijndael implementation, don’t know if I can call it a bug but it doesn’t work correctly in CBC mode. I’ll show what my problem is and how I fix it. And later on I’ll share my source code.

in rijndael-api-fst.c, function blockEncrypt()


case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
break;

You can see the Initial Vector is assigned each iteration, HOWEVER, only assigned in this execution cycle. Since I’m working on file encryption, surely I cannot fix the buffer size in advance because the file size is unknown. I made a loop to continuously read 1024 bytes from input file until the feof(fp) is reached. Therefore, in each cycle of loop I’ll have at most 1024 bytes of data in buffer to be encrypted. Since Rijndael is a 128-bit block cipher, I got numBlocks=64 (in maximum) during each blockEnrypt execution. Well, now, you may find out what problem I’m addressing here. Ya, cipher->IV is not updated. Let me trace the code this way.

1. execute the problem with IV = {0};
2. file size > 1024 bytes;
3. goto blockEncrypt()
4. run rijndaelEncrypt()
5. iv is updated as last outBuffer
6. after 64 blocks is executed, break.
7. next 1024 bytes file buffer come in
8. start blockEncrypt()
9. .. wow-oh! what’s the IV now?

Right, the Initial Vector in CBC mode is not connected, it refreshed each time blockEncrypt() is called. So I simply add one line. Now the code looks like this


case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
memcpy(cipher->IV, outBuffer, 16);
input += 16;
outBuffer += 16;
}
break;

This problem exists in blockDecrypt() as well, this time it doesn’t update iv, instead of cipher->IV, in each decrypt iteration. I will just give my version of blockDerypt here.


case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= ((u32*)iv)[0];
((u32*)block)[1] ^= ((u32*)iv)[1];
((u32*)block)[2] ^= ((u32*)iv)[2];
((u32*)block)[3] ^= ((u32*)iv)[3];
iv = input;
memcpy(outBuffer, block, 16);
memcpy(cipher->IV, input, 16);
input += 16;
outBuffer += 16;
}
break;

So, if you’ve been suffered from similar problem, hope this message is helpful to you. If you find my article incorrect, please let me know. The original authors and copyright statement of this implementation is in the readme file. Enjoy. 🙂

Advertisements

Comments»

1. touranku - July 10, 2008

T_T

thaaaaaank you
billion thank to you

this help me a lot


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: