1

I have a simple C program for aes256 encryption. It is linked with openssl library (-lcrypto). The core of the program are following few lines:

AES_set_encrypt_key(key32 ,256 ,&aes_ks3);

while( len = fread( buf ,1 ,4096, fp) ){
    if( 4096 != len )
        break;
    AES_cbc_encrypt(buf ,buf ,len ,&aes_ks3 ,iv ,AES_ENCRYPT);
    fwrite(buf ,1 ,len ,wfp);
}

AES_cbc_encrypt(buf ,buf ,len+padding_len ,&aes_ks3, iv,AES_ENCRYPT);
fwrite(buf ,1 ,len+padding_len ,wfp);

I am only using standard openssl library functions for encryption (ie. I am not using my own functions). I can encrypt same file, using same key and IV with openssl command:

openssl enc -aes-256-cbc -in FILE.in -out FILE.out -K $key -iv $iv

And I get identical output file (thus verifying that my program works correctly).

However, my program consistently runs is 4-5 times slower than the openssl command. They are both using the same routines, abd are both linked with the same library.

How is that possible?

How can I investigate why?

UPDATE:

Here are the actual numbers for encrypting same file with 1) openssl, 2) my program:

1) openssl:

real    0m0.238s
user    0m0.196s
sys     0m0.040s

2) my program:

real    0m1.006s
user    0m0.964s
sys     0m0.040s
jww
  • 97,681
  • 90
  • 411
  • 885
Martin Vegter
  • 136
  • 9
  • 32
  • 56
  • what's `RW_SIZE` and `FREAD_COUNT`? Without any more information I would probably bet that's where your bottleneck is. – Art Jan 25 '16 at 13:23
  • @Art - I have replaced `RW_SIZE` and `FREAD_COUNT ` by their corresponding numbers. – Martin Vegter Jan 25 '16 at 13:32
  • I guess my bet wasn't that great. 4096 sounds like it's plenty of buffer to not cause a lot of overhead. What are the actual performance numbers of your program vs. the openssl command? – Art Jan 25 '16 at 13:48
  • How often does the program enter the loop? Maybe the performance issue is with the file operations and not crypto functions. Try reading only at the beginning and writing only at the end of the program. Anyway, be aware that you're using deprecated API - you should use EVP suite and not such primitives. – Leśny Rumcajs Jan 25 '16 at 13:49
  • @art - I have added the actual numbers (times) – Martin Vegter Jan 25 '16 at 14:22
  • Also see [How can I check if OpenSSL is support/use the Intel AES-NI?](http://stackoverflow.com/q/25284119) – jww Jan 26 '16 at 16:56

1 Answers1

3

By calling the AES functions directly, you lose all the optimizations provided by the EVP layer. In particular, the EVP layer supports AES intrinsics, which makes a huge difference on CPUs that support them.

Community
  • 1
  • 1
David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Well, 2 to 7 times depending on how fast the CPU is itself last time I checked. Quite a difference, but the window is shrinking. Note that AES-NI still has advantages with regards to e.g. side channel attacks, so there is more to that instruction than just speed (just additional info after +1). – Maarten Bodewes Jan 25 '16 at 15:18
  • @David Schwartz - is it possible to use the `AES-NI` cpu instructions directly (without using EVP) ? ie is there some parameter to set when using `AES_cbc_encrypt` ? – Martin Vegter Jan 25 '16 at 15:48
  • It's almost certainly going to be a compile-time parameter. Have you tried `-O3` and `-maes`? – Thomas M. DuBuisson Jan 25 '16 at 17:16
  • @MartinVegter I wouldn't suggest it, but you can look at the source code in `crypto/evp/e_aes.c` to see the functions that the EVP layer uses to decide which AES functions to call. – David Schwartz Jan 25 '16 at 18:21
  • @David Schwartz - I have solved the problem by using the `AES-NI` functions, instead of the previous general `AES` functions. Thanks for the help. – Martin Vegter Jan 25 '16 at 19:48