Decryption Encrypting with the EVP API

157 Note that the number of bytes written by EVP_EncryptFinal should always be 8 when using 64-bit blocks and when padding is enabled.

6.2.5 Decryption

As expected, the decryption API looks similar to the encryption API. After cipher initialization, two methods are involved, EVP_DecryptUpdate and EVP_DecryptFinal . You can pass as much data as you want into EVP_DecryptUpdate . When using a block-based mode ECB or CBC, you can pass in partial blocks of text, but EVP_DecryptUpdate will output only whole blocks. The rest will be stored until there is more data to be processed, or until EVP_DecryptFinal is called. Moreover, if the contexts cached ciphertext plus the length of the new ciphertext is exactly block-aligned, the entire final block will be held in the context instead of getting output. With CFB and OFB modes and with stream ciphers, theres no padding, so the size of the resulting ciphertext will be equal to the size of the plaintext. If using a block-based mode, EVP_DecryptFinal first checks to see if the padding on the last block is in the right format. If not, the function returns 0, signifying failure. Otherwise, it flushes any remaining data to the buffer passed in as the second argument, and writes the number of bytes flushed into the third argument, a reference parameter. For other modes, this call does nothing. Example 6-5 shows a simple function that decrypts a block of encrypted text into a dynamically allocated buffer and returns it. This function can be used to incrementally decrypt, and thus requires EVP_DecryptFinal to be called when a block-based mode is used. Of course, EVP_DecryptInit should always be called before passing a context to this function. Example 6-5. Decrypting ciphertext char decrypt_exampleEVP_CIPHER_CTX ctx, char ct, int inl { Were going to null-terminate the plaintext under the assumption its non-null terminated ASCII text. The null can be ignored otherwise. char pt = char mallocinl + EVP_CIPHER_CTX_block_sizectx + 1; int ol; EVP_DecryptUpdatectx, pt, ol, ct, inl; if ol theres no block to decrypt { freept; return NULL; } pt[ol] = 0; return pt; } As is the case with encryption, factoring in the ciphers block length is strictly only necessary when using a block-based cipher mode. Using the above function, and the ones we previously developed, lets look at Example 6-6 , which encrypts a 15-byte string using Blowfish in CBC mode, then passes it into decrypt_example in two parts. Note, we use the macro EVP_MAX_BLOCK_LENGTH , which exists only in 0.9.7 and 158 later. If you are using an earlier version of OpenSSL, you can define this macro to the value 64, which is the largest possible block size in 0.9.6c and earlier. Example 6-6. Using the example encryption and decryption functions int mainint argc, char argv[] { EVP_CIPHER_CTX ctx; char key[EVP_MAX_KEY_LENGTH]; char iv[EVP_MAX_IV_LENGTH]; char ct, out; char final[EVP_MAX_BLOCK_LENGTH]; char str[] = 123456789abcdef; int i; if seed_prng { printfFatal Error Unable to seed the PRNG\n; abort; } select_random_keykey, EVP_MAX_KEY_LENGTH; select_random_iviv, EVP_MAX_IV_LENGTH; EVP_EncryptInitctx, EVP_bf_cbc, key, iv; ct = encrypt_examplectx, str, strlenstr, i; printfCiphertext is d bytes.\n, i; EVP_DecryptInitctx, EVP_bf_cbc, key, iv; out = decrypt_examplectx, ct, 8; printfDecrypted: s\n, out; out = decrypt_examplectx, ct + 8, 8; printfDecrypted: s\n, out; if EVP_DecryptFinalctx, final, i { printfPadding incorrect.\n; abort; } final[i] = 0; printfDecrypted: s\n, final; } If we run this example, the first time we try to output decrypted plaintext, we will see nothing, even though we fed the decryption routine a full block of data. Note that when we feed the remainder of the data, we are passing in eight bytes, because the encryption routine padded the data to a block-aligned length. At that point, one block will be output, and the second block will be held in reserve until there is more data, or until EVP_DecryptFinal is called. If we were to change the cipher to RC4, the above example would compile, but give slightly incorrect output. The length of the encrypted text would be 15 bytes, not 16, due to the lack of padding. As a result, passing in 16 bytes of ciphertext to the decrypt routine will cause a block of garbage to be decrypted. Changing the third argument in the second call to decrypt_example to seven fixes the problem.

6.2.6 Handling UDP Traffic with Counter Mode