<div dir="ltr"><div style="font-size:12.8px"><span style="font-size:12.8px">Using the guide posted here:</span><div style="font-size:12.8px"><a href="https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption" target="_blank">https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption</a></div></div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">I was getting a fairly large amount of bytes "still reachable", so I decided to throw in all of the options to free up whatever was left over.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Originally, all that was suggested in the wiki was to EVP_cleanup() and ERR_free_strings(). But by adding in CRYPTO_cleanup_all_ex_data(), ERR_remove_thread_state(0), ENGINE_cleanup(), and CONF_modules_unload(0), I was able to significantly cut down on the bytes still reachable.</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Full leak check below. The code is the exact same as in the wiki, but with the additions mentioned above.</div><div style="font-size:12.8px"><br></div><div><div style="font-size:12.8px">root@openssl:~# valgrind ./test --leak-check=full --tool=memcheck -v</div><div style="font-size:12.8px">==31040== Memcheck, a memory error detector</div><div style="font-size:12.8px">==31040== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.</div><div style="font-size:12.8px">==31040== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info</div><div style="font-size:12.8px">==31040== Command: ./test --leak-check=full --tool=memcheck -v</div><div style="font-size:12.8px">==31040== </div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://ld-2.21.so/" target="_blank">ld-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- Ignoring non-Dwarf2/3/4 block in .debug_info</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://ld-2.21.so/" target="_blank">ld-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- Last block truncated in .debug_info; ignoring</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://ld-2.21.so/" target="_blank">ld-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://libc-2.21.so/" target="_blank">libc-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- Ignoring non-Dwarf2/3/4 block in .debug_info</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://libc-2.21.so/" target="_blank">libc-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- Last block truncated in .debug_info; ignoring</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://libc-2.21.so/" target="_blank">libc-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://libdl-2.21.so/" target="_blank">libdl-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- Ignoring non-Dwarf2/3/4 block in .debug_info</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://libdl-2.21.so/" target="_blank">libdl-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- Last block truncated in .debug_info; ignoring</div><div style="font-size:12.8px">--31040-- WARNING: Serious error when reading debug info</div><div style="font-size:12.8px">--31040-- When reading debug info from /lib/x86_64-linux-gnu/<a href="http://libdl-2.21.so/" target="_blank">libdl-2.21.so</a>:</div><div style="font-size:12.8px">--31040-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4</div><div style="font-size:12.8px">Ciphertext is:</div><div style="font-size:12.8px">0000 - e0 6f 63 a7 11 e8 b7 aa-9f 94 40 10 7d 46 80 a1   .oc.......@.}F..</div><div style="font-size:12.8px">0010 - 17 99 43 80 ea 31 d2 a2-99 b9 53 02 d4 39 b9 70   ..C..1....S..9.p</div><div style="font-size:12.8px">0020 - 2c 8e 65 a9 92 36 ec 92-07 04 91 5c f1 a9 8a 44   ,.e..6.....\...D</div><div style="font-size:12.8px">Decrypted text is:</div><div style="font-size:12.8px">The quick brown fox jumps over the lazy dog</div><div style="font-size:12.8px">==31040== </div><div style="font-size:12.8px">==31040== HEAP SUMMARY:</div><div style="font-size:12.8px">==31040==     in use at exit: 240 bytes in 8 blocks</div><div style="font-size:12.8px">==31040==   total heap usage: 3,295 allocs, 3,287 frees, 121,451 bytes allocated</div><div style="font-size:12.8px">==31040== </div><div style="font-size:12.8px">==31040== LEAK SUMMARY:</div><div style="font-size:12.8px">==31040==    definitely lost: 0 bytes in 0 blocks</div><div style="font-size:12.8px">==31040==    indirectly lost: 0 bytes in 0 blocks</div><div style="font-size:12.8px">==31040==      possibly lost: 0 bytes in 0 blocks</div><div style="font-size:12.8px">==31040==    still reachable: 240 bytes in 8 blocks</div><div style="font-size:12.8px">==31040==         suppressed: 0 bytes in 0 blocks</div><div style="font-size:12.8px">==31040== Rerun with --leak-check=full to see details of leaked memory</div><div style="font-size:12.8px">==31040== </div><div style="font-size:12.8px">==31040== For counts of detected and suppressed errors, rerun with: -v</div><div style="font-size:12.8px">==31040== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Code:</div><div style="font-size:12.8px"><br></div></div><div><div><span style="font-size:12.8px">#include <openssl/conf.h></span></div><div><span style="font-size:12.8px">#include <openssl/evp.h></span></div><div><span style="font-size:12.8px">#include <openssl/err.h></span></div><div><span style="font-size:12.8px">#include <openssl/engine.h></span></div><div><span style="font-size:12.8px">#include <string.h></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">void handleErrors(void)</span></div><div><span style="font-size:12.8px">{</span></div><div><span style="font-size:12.8px">  ERR_print_errors_fp(stderr);</span></div><div><span style="font-size:12.8px">  abort();</span></div><div><span style="font-size:12.8px">}</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,</span></div><div><span style="font-size:12.8px">  unsigned char *iv, unsigned char *plaintext)</span></div><div><span style="font-size:12.8px">{</span></div><div><span style="font-size:12.8px">  EVP_CIPHER_CTX *ctx;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  int len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  int plaintext_len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Create and initialise the context */</span></div><div><span style="font-size:12.8px">  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Initialise the decryption operation. IMPORTANT - ensure you use a key</span></div><div><span style="font-size:12.8px">   * and IV size appropriate for your cipher</span></div><div><span style="font-size:12.8px">   * In this example we are using 256 bit AES (i.e. a 256 bit key). The</span></div><div><span style="font-size:12.8px">   * IV size for *most* modes is the same as the block size. For AES this</span></div><div><span style="font-size:12.8px">   * is 128 bits */</span></div><div><span style="font-size:12.8px">  if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))</span></div><div><span style="font-size:12.8px">    handleErrors();</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Provide the message to be decrypted, and obtain the plaintext output.</span></div><div><span style="font-size:12.8px">   * EVP_DecryptUpdate can be called multiple times if necessary</span></div><div><span style="font-size:12.8px">   */</span></div><div><span style="font-size:12.8px">  if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))</span></div><div><span style="font-size:12.8px">    handleErrors();</span></div><div><span style="font-size:12.8px">  plaintext_len = len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Finalise the decryption. Further plaintext bytes may be written at</span></div><div><span style="font-size:12.8px">   * this stage.</span></div><div><span style="font-size:12.8px">   */</span></div><div><span style="font-size:12.8px">  if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();</span></div><div><span style="font-size:12.8px">  plaintext_len += len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Clean up */</span></div><div><span style="font-size:12.8px">  EVP_CIPHER_CTX_free(ctx);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  return plaintext_len;</span></div><div><span style="font-size:12.8px">}</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,</span></div><div><span style="font-size:12.8px">  unsigned char *iv, unsigned char *ciphertext)</span></div><div><span style="font-size:12.8px">{</span></div><div><span style="font-size:12.8px">  EVP_CIPHER_CTX *ctx;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  int len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  int ciphertext_len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Create and initialise the context */</span></div><div><span style="font-size:12.8px">  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Initialise the encryption operation. IMPORTANT - ensure you use a key</span></div><div><span style="font-size:12.8px">   * and IV size appropriate for your cipher</span></div><div><span style="font-size:12.8px">   * In this example we are using 256 bit AES (i.e. a 256 bit key). The</span></div><div><span style="font-size:12.8px">   * IV size for *most* modes is the same as the block size. For AES this</span></div><div><span style="font-size:12.8px">   * is 128 bits */</span></div><div><span style="font-size:12.8px">  if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))</span></div><div><span style="font-size:12.8px">    handleErrors();</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Provide the message to be encrypted, and obtain the encrypted output.</span></div><div><span style="font-size:12.8px">   * EVP_EncryptUpdate can be called multiple times if necessary</span></div><div><span style="font-size:12.8px">   */</span></div><div><span style="font-size:12.8px">  if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))</span></div><div><span style="font-size:12.8px">    handleErrors();</span></div><div><span style="font-size:12.8px">  ciphertext_len = len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Finalise the encryption. Further ciphertext bytes may be written at</span></div><div><span style="font-size:12.8px">   * this stage.</span></div><div><span style="font-size:12.8px">   */</span></div><div><span style="font-size:12.8px">  if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();</span></div><div><span style="font-size:12.8px">  ciphertext_len += len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Clean up */</span></div><div><span style="font-size:12.8px">  EVP_CIPHER_CTX_free(ctx);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  return ciphertext_len;</span></div><div><span style="font-size:12.8px">}</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">int main (void)</span></div><div><span style="font-size:12.8px">{</span></div><div><span style="font-size:12.8px">  /* Set up the key and iv. Do I need to say to not hard code these in a</span></div><div><span style="font-size:12.8px">   * real application? :-)</span></div><div><span style="font-size:12.8px">   */</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* A 256 bit key */</span></div><div><span style="font-size:12.8px">  unsigned char *key = (unsigned char *)"01234567890123456789012345678901";</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* A 128 bit IV */</span></div><div><span style="font-size:12.8px">  unsigned char *iv = (unsigned char *)"01234567890123456";</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Message to be encrypted */</span></div><div><span style="font-size:12.8px">  unsigned char *plaintext =</span></div><div><span style="font-size:12.8px">                (unsigned char *)"The quick brown fox jumps over the lazy dog";</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Buffer for ciphertext. Ensure the buffer is long enough for the</span></div><div><span style="font-size:12.8px">   * ciphertext which may be longer than the plaintext, dependant on the</span></div><div><span style="font-size:12.8px">   * algorithm and mode</span></div><div><span style="font-size:12.8px">   */</span></div><div><span style="font-size:12.8px">  unsigned char ciphertext[128];</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Buffer for the decrypted text */</span></div><div><span style="font-size:12.8px">  unsigned char decryptedtext[128];</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  int decryptedtext_len, ciphertext_len;</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Initialise the library */</span></div><div><span style="font-size:12.8px">  ERR_load_crypto_strings();</span></div><div><span style="font-size:12.8px">  OpenSSL_add_all_algorithms();</span></div><div><span style="font-size:12.8px">  OPENSSL_config(NULL);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Encrypt the plaintext */</span></div><div><span style="font-size:12.8px">  ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv,</span></div><div><span style="font-size:12.8px">                            ciphertext);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Do something useful with the ciphertext here */</span></div><div><span style="font-size:12.8px">  printf("Ciphertext is:\n");</span></div><div><span style="font-size:12.8px">  BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Decrypt the ciphertext */</span></div><div><span style="font-size:12.8px">  decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv,</span></div><div><span style="font-size:12.8px">    decryptedtext);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Add a NULL terminator. We are expecting printable text */</span></div><div><span style="font-size:12.8px">  decryptedtext[decryptedtext_len] = '\0';</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Show the decrypted text */</span></div><div><span style="font-size:12.8px">  printf("Decrypted text is:\n");</span></div><div><span style="font-size:12.8px">  printf("%s\n", decryptedtext);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  /* Clean up */</span></div><div><span style="font-size:12.8px">  EVP_cleanup();</span></div><div><span style="font-size:12.8px">  ERR_free_strings();</span></div><div><span style="font-size:12.8px">  ENGINE_cleanup();</span></div><div><span style="font-size:12.8px">  CONF_modules_unload(0);</span></div><div><span style="font-size:12.8px">  CRYPTO_cleanup_all_ex_data();</span></div><div><span style="font-size:12.8px">  ERR_remove_thread_state(0);</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">  return 0;</span></div><div><span style="font-size:12.8px">}</span></div></div></div>